一个有趣的代码问题

OldNewThing发布了一篇很有意思的文章http://blogs.msdn.com/oldnewthing/archive/2010/01/20/9950638.aspx

The wrong way to determine the size of a buffer

A colleague of mine showed me some code from a back-end program on a web server. Fortunately, the company that wrote this is out of business. Or at least I hope they’re out of business!

size = 16384;

while (size && IsBadReadPtr(buffer, size))

{ size--; }

高人就是高人,这个代码其实还是需要好好想一想才能明白为何有问题。

IsBadReadPtr的意思是尝试去读一个不属于自己进程的内存地址,因为指针越界在大多数情况下都是代表错误发生。但是这个函数实际上并不是那么好用,具体原因可以看OldNewThing的这篇文章http://blogs.msdn.com/oldnewthing/archive/2006/09/27/773741.aspx 介绍的非常详细。

回到这个问题上,在OldNewThing的文章中介绍的非常清楚“But guard page exceptions are raised only once.”,也就是说,IsBadReadPtr将只会有效一次(?need to double check),这个代码逻辑就是有问题的。

再把其中包含的问题列一下,主要参考了文章后的留言。

1)16384这个16K大小来的莫名其妙,当然不排除在某些特定软件设计中,最大就是这个大小。

2)第二个问题,IsBadReadPtr并不是那么好用。

3)这个计算得到的值未必正确。

那么我们该如何获取buffer的大小呢?

在c-faq中告诉我们,通常情况下是没有解决办法的,只能自己保存这个buffer大小。办法也很简单,我们需要申请的时候就把buffer大小记住,需要知道的时候,查找一下就知道了,或者是使用某种数据结构,把buffer的大小以及其他信息放在开头固定的一块大小就行了。

如果是windows,那么有一些特定的办法。可以用_msize来获得malloc申请的buffer。

allocated with LocalAlloc, use LocalSize. For HeapAlloc, use HeapSize. For GlobalAlloc, use GlobalSize,如果使用CoTaskMemalloc,可以先用CoGetMalloc拿到一个IMalloc接口,然后调用GetSize()

这些函数到底好用不好用,还是得靠你自己多测试。最简单牢靠的办法还是自己保存这个size信息。

Some interesting Lua code test

When I read the book <the ruby way>, I get some interesting code that need to run in Lua. (I will test following code in Lua5.14 for windows package.)

 1: print( 5 % 3)

 2: print( -5 % 3)

 3: print( 5 % -3)

 4: print(-5 % -3)

The result will be 2, 1, -1, -2.

 1: if not nil then

 2: print("not nil")

 3: end

 4:  

 5: if not false then

 6: print("not false")

 7: end

 8:  

 9: if 0 then

 10: print("0")

 11: end

 12:  

 13: if "" then

 14: print("empty string")

 15: end

The result will be "not nil", "not false", "0", "empty string", in Lua, only nil and false will be FALSE in condition checking.

 1: for i = 1, 5 do

 2: print(i)

 3: i = i + 5

 4: print(i)

 5: print("")

 6: end

OK, the result will be 1  6, 2  7, 3  8, 4  9, 5  10, you could see the index variable "i" is not changed for the for-loop, and you could assign new value (i=i+5) to it in the for range, but it will restore back to the loop index value again.

 1: local x, y = {}

 2: print(x)

 3: print(y)

 4:  

 5: y = x

 6: print(y)

 7: table.insert(y, "aa")

 8: print(x[1])

It will print like "table: 003CACB0" "nil" "table: 003CACB0" "aa".

Two thing need to note, local x, y = {} will only initialize the "x". Another is the y will have same address with x if x is a table, and insert to table y will cause x changes too. It seems like in c or c++ only copy the pointer address, not copy the value with the pointer.

吾家有女初长成

上周末回到萌萌爷爷奶奶家,看到一件非常有意思的事情,一定要写写。

话说萌萌到了4岁以后,自己的主意越来越多,穿什么衣服,戴什么发卡都要自己定,不好看的不穿。据她妈妈说,上次她去训练的时候,戴了一头的发卡,数数足足有13个,都是她自己别的。

晚饭还是吃的涮羊肉,比较省事。吃完了以后,萌萌就开始嫌自己的辫子不好看,要重新扎。

只见她小手把头发捋顺,挑起一缕头发,熟练地用皮筋把头发扎成一个小马尾,最后还把头发拽拽,让皮筋能扎到辫子根。oh my girl,你简直是太神奇了。(可惜没有带相机,没法拍视频)扎了几次,她还是感觉不太好看,于是让爷爷又给她扎成羊角辫。

头发弄好以后,就大概折腾了半个多小时了,然后又去把自己的漂亮发卡都找出来。然后对着镜子一个个别在头上,来来回回的又是整了半个多小时,就是弄个头发就整了快一个小时,而且一点也不觉得烦。好不好看不论,这份爱臭美的个性到底像谁呢?难道是随她妈妈?