这两天一直在研究一个Crash问题,其表现非常明显就是Memory Heap被破坏了,但是由于破坏堆的现场无法准确定位,发生Crash的地方已经不是现场,所以一直都没找到原因。最后只好将代码Roll Back回去,一个一个模块的试,最终发现问题出现在某一个模块中指针类型的强制转换引起的虚函数调用错误上。
错误是这样的,有一个指针是A类型的,被强制转换为B类型,并且通过B类型调用B的虚函数,但是实际上调用的虚函数地址在A的虚函数表中。由于两者参数并不相同,所以导致错误出现。
B类型的函数参数中有一个std::vector类型,由于c++遵循cdecl调用约定,所以是由被调用端负责清理堆栈,这时候就会调用std::vector的析构函数,而实际上该参数已经在调用A的虚函数时被破坏了,在执行完这个函数之后,栈是正确的,但是堆已经被std::vector的析构函数破坏,所以出现了heap Corruption的错误。
Heap Corruption是C++开发中非常棘手的一个问题,其引起的Crash有两点非常难以琢磨:
1. 在Debug版较难或者不出现,在Release版常常出现
2. 在Release版本上也是在非现场出现,而且往往在大量释放内存的地方出现。
相信应该有比较好C++的Heap Corruption工具,BoundChecker曾经用过,可惜太复杂不会用,不知道有没有非常有效的检测Heap Corruption工具。