原因:
1.通常是有指针越界造成的,仔细检查代码有没有越界的行为。
2.指针在程序运行中位置发了变化,例如指针a,执行了a++操作。
最近在处理一个 App crash的问题时,异常诡异,仅仅在release版本下可以复现(但不是必现),debug版本不能复现。好在用QtCreator通过debug跑release版本的代码时可以截取到crash时的函数调用栈。函数调用栈显示在一个析构函数中free某一个地址的时候出的问题。
这样就大大缩小了搜索的范围,问题就定位在第7行的函数中析构第6行的类对象的时候。所以有两个出发点:
- Check第7行的函数实现,发现函数中一共有两个地方定义了该类的对象(均为栈对象),既然不是用new分配的内存,那么只有一种可能,就是在代码块结束或者整个函数返回时依次释放栈对象的时候析构的。
- Check第6行析构函数,发现有很多释放结构体指针(数组)的代码,release模式的代码无法加断点(加了也不会停),无法具体定位到是在释放哪个指针的时候出的错。只有一个方法,修改这两个函数文件所在的pro文件,在release分支中删除DEFINES += QT_NO_DEBUG_OUTPUT QT_NO_WARNING_OUTPUT,以允许release模式的log输出,然后依次在上图析构函数中加log(log加多了不容易复现,所以依次加一两个)逐步确认到在倒数第二行出现非法指针(为了描述方便,假设这个指针是obj->struct1)。
这样,虽然知道了哪个指针是非法的,但是上图第7行函数中有两个地方定义了该类的栈对象,不好判断是哪个栈对象出的问题。方法仍然是加log,在这两个栈对象定义的下一行,分别输出一行log,打印出obj->struct1的地址,有了这个地址,就可以结合crash log, 进行对比。最终定位到第二个栈对象, 发现二者有0x2000的offset。
所以定位在检查使用obj->struct1的时候,哪些地方有可能做指针++的动作。