最近遇到一个问题,在debug模式下怎么运行结果都是正确的,而release时会出现一些诡异的问题,但是问题又诡异的很,比如我printf几句无关痛痒的log信息,可能现象又对了。
只好在汇编模式下一行一行的跟下去,最终发现了问题的所在。
问题是这样的,我有一处代码用到了zlib的解压:
int uncompress
(Bytef * dest, uLongf * destLen, const Bytef * source, uLong sourceLen);
因为之前没用过也没有仔细看参数传递规则,不知道deslen一定要传入目标buffer dest的大小,以为他只是一个返回值,于是就这样调用了:
uLongf destLen;
uncompress(dest, destLen, ...);
这里犯了两个错误,一是没有检查uncompress的返回值(这里不怪我,因为我调用的函数是前人在uncompress上封装了一层,然后就没返回值了)。然后呢,诡异的问题就出现了:
VC的debug模式局部变量会默认的赋值为0xcdcdcdcd,这是debug下正确的原因,因为uncompress会认为我的传入dest是足够大的(事实上是刚刚够,因为解压之前我就知道这个buffer的大小),所以就高高兴兴地去解压了,然后目标buffer也足够大不会越界,然后,然后就一切正常了...
而release下VC就不会给局部变量赋值了,然后呢,在调用的时候有时(对,就是有时,没初始化,这个值就是随机的!)就会发现目标buffer dest的大小不够用了,然后就调用失败了,然后我调用的函数没有返回值,然后认为一切正常,然后dest里的值还是初始值,然后就效果不对了,然后就傻逼了...
归根结底呢,是坏习惯的问题,首先,应该检查返回值,这是前人的错,我可以无耻的推卸掉,但是变量没初始化的过错就是万万退不掉了,假使我即使不知道destLen要传实际dest的大小,我把它初始化成0,那么至少会在debug的时候问题就显现出来,不至于在release中无所适从,一个简单的问题用了半天的时间才发现根结所在。
所以结论就是,定义变量时一定要初始化,哪怕看起来很无用很无聊,至少这样会减少很多犯错的几率!