混用不同版本的 libc 造成程序崩溃

程序发生崩溃,调试器提示崩溃发生在 libc 的 free() 函数里面:

Debug Assertion Failed: _CrtIsValidHeapPointer(pUserData)

初步判断,可能是堆(Heap)被写坏了。

于是修改代码,在程序初始化的地方,调用了 _CrtSetDbgFlag 来设置一些调试的开关,希望调试器能够捕获到堆被写坏的操作。以下是这个 API 的原型,更多信息可以参考文档 https://msdn.microsoft.com/en-us/library/5at7yxcs(v=vs.110).aspx

int _CrtSetDbgFlag(
   int newFlag
);

Flags:
  o _CRTDBG_ALLOC_MEM_DF
  o _CRTDBG_CHECK_ALWAYS_DF
  o _CRTDBG_CHECK_CRT_DF
  o _CRTDBG_DELAY_FREE_MEM_DF
  o _CRTDBG_LEAK_CHECK_DF

然而,调试下来并没有看到堆被写坏的操作。

继续调试,终于发现了问题。程序运行时会依赖动态库 A 和 B,其中 A 引用了 release 编译的 libc,B 引用了 debug 编译的 libc。在 A 里 malloc() 出来的内存,传递到 B 里使用 free() 来释放的时候,B 依赖的 libc 肯定无法处理,所以出错了。

确实蛮凌乱的。。

定位了原因,修改就很简单了,在这几个模块的编译及链接属性里,选择相同的 libc 即可。(这里有 libc 编译选项的说明。)

Read More: