调试代码,有时候会遇到很奇怪的现象,比如明明调用A函数,单步却进了B函数;比如明明if判断结果该为true,却进了false的分支;比如明明刚对一个int成员变量进行了赋值,但是完全没效果。感觉代码在乱跑,完全不能用正常的思路来思考到底哪儿出了错,只能感叹奇了怪了。
在过往的经历里,代码乱跑的原因有两种:
一,有汉字注释的文件,编码不对。修改编码重新编译可以解决。
二,链接库时,头文件与库文件不匹配。这个常见于想要调试库,把库代码链接进来后,忘记把库的头文件也换成库代码里的那份。
而今天,代码乱跑玩出了新花样。
简单的说,就是库代码里有类A,类B。 A包含B的成员变量。
class A
{
B b;
int c;
};
奇怪的是,在A的构造函数和init函数里,对c进行赋值,没有任何效果。
最终找到问题的原因,B的头文件里有如下代码:
class B
{
public:
……
#if (defined OS_OSX) || (defined OS_IOS) || (defined OS_IOSSIMULATOR)
char m_Name[NAME_MAX+1];
#endif
};
库文件生成时,定义了宏OS_IOS。而链接库的项目没有定义OS_IOS。从而,在B的初始化操作中,对m_semName的赋值踩坏了内存。而对于c的赋值,根本是赋值到了整个类A的内存之后不知道哪个位置去了。所以看着赋值无效。
把定位问题的过程整理如下,希望能帮到遇到相似问题的人:
- 发现修改代码后,大量出现崩溃。崩溃地点在新改代码里居多,其他地方随机也有。
- 查看崩溃的堆栈及调用里打的日志,感觉不合理。结合随机崩溃,猜测代码跑乱了。
- 检查文件编码及头文件与库文件的匹配情况,确认没有问题。
- 注调新加代码,恢复正常。
- 加回代码,单步跟踪,发现A类c变量异常,赋值无效。
- 分批注掉添加的代码,再测试崩溃情况。发现注掉A中的B变量后,不再崩溃。但查看B的初始化代码并没有越界的可能。
- 单步跟踪A的初始化,查看c变量的值是什么时候变化的。发现是对B变量的m_Name进行写操作时。
- 查看c变量的内存,发现与m_Name的内存是一样的。
- 切回外层,发现B变量中并没有m_Name变量。
- 检查宏定义,发现库文件里有OS_IOS,但链接库的项目中并没有这个宏。
在查问题的这个过程中,我抓耳挠腮,郁闷很多次,叹气很多次,丢笔很多次。问题很严重,我却没有思路。我找人求助,虽然获得了友好的帮助,却并没有实际的促进问题的解决。现在回头来看,解决这个问题最大的难点反而在于,我想象不到会是什么可能,所以我觉得自己无法解决,于是,我无法安下心来去尝试解决。我想着别人可能会知道答案,也许别人会有思路,可大牛们的答案与思路,很多也不过是他们上次,上上次,上上上次认真的调试了很久,尝试得多了便有了经验。我不该总想着走捷径,让别人给我答案。我更应该相信自己,我,可以的。
网友评论