程序员

奇了怪的代码跑乱

2018-04-27  本文已影响0人  妖精不语

调试代码,有时候会遇到很奇怪的现象,比如明明调用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的内存之后不知道哪个位置去了。所以看着赋值无效。

把定位问题的过程整理如下,希望能帮到遇到相似问题的人:

  1. 发现修改代码后,大量出现崩溃。崩溃地点在新改代码里居多,其他地方随机也有。
  2. 查看崩溃的堆栈及调用里打的日志,感觉不合理。结合随机崩溃,猜测代码跑乱了。
  3. 检查文件编码及头文件与库文件的匹配情况,确认没有问题。
  4. 注调新加代码,恢复正常。
  5. 加回代码,单步跟踪,发现A类c变量异常,赋值无效。
  6. 分批注掉添加的代码,再测试崩溃情况。发现注掉A中的B变量后,不再崩溃。但查看B的初始化代码并没有越界的可能。
  7. 单步跟踪A的初始化,查看c变量的值是什么时候变化的。发现是对B变量的m_Name进行写操作时。
  8. 查看c变量的内存,发现与m_Name的内存是一样的。
  9. 切回外层,发现B变量中并没有m_Name变量。
  10. 检查宏定义,发现库文件里有OS_IOS,但链接库的项目中并没有这个宏。

在查问题的这个过程中,我抓耳挠腮,郁闷很多次,叹气很多次,丢笔很多次。问题很严重,我却没有思路。我找人求助,虽然获得了友好的帮助,却并没有实际的促进问题的解决。现在回头来看,解决这个问题最大的难点反而在于,我想象不到会是什么可能,所以我觉得自己无法解决,于是,我无法安下心来去尝试解决。我想着别人可能会知道答案,也许别人会有思路,可大牛们的答案与思路,很多也不过是他们上次,上上次,上上上次认真的调试了很久,尝试得多了便有了经验。我不该总想着走捷径,让别人给我答案。我更应该相信自己,我,可以的。

上一篇 下一篇

猜你喜欢

热点阅读