我晕,一个低级错误导致我DEBUG两天(std::string c_str()的问题)

起因是这样的,为了方便读取RO里的素材,我在OPenRO里加入了一个第三方库,他的作用主要就是负责提取RO素材数据,并把他们放在heap里,程序退出他会自动释放。

但是莫名其妙的问题随之而来了:每次程序退出都会弹窗提示:“******,其原因可能是堆被损坏,这也说明****加载的Dll可能有问题”。看见这个,我第一反应是Dll里分配的内存在程序里释放时,Dll与exe使用了不同的C运行时库。但是我使用的这个第三方库根本就是一个静态lib啊,而且使用的C运行时库版本绝对是一样的。

我就郁闷了,剩下只有一种解释,这个lib有问题,可能其中的处理会导致堆损坏,比如越界写入,delete不存在的内存等。于是我就抱着找出这个BUG的信念,从头到尾把这个库给看了一遍。

一天完了,一无所获。

第二天,发现了更诡异的问题,我用这个第三方库加载了不同的素材,程序退出依然弹窗提示,但是从调试堆栈窗口看到的结果却不一样,显示的是我自己的模块堆损坏。这样,我又把自己的程序检查了一遍,还是没发现问题。。。(其实后来其实发现这个问题也是理所当然,因为整个堆损坏了嘛,可能覆盖了其他内存块)

我开始怀疑是我WIN7下不兼容VS2005的问题。又难得转成VS2008,正准备放弃这个BUG待以后解决时,采用了Google到的一个方法,在程序代码中加入:

_CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_DELAY_FREE_MEM_DF | _CRTDBG_CHECK_EVERY_1024_DF | _CRTDBG_CHECK_CRT_DF);


_CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_DEBUG | _CRTDBG_MODE_WNDW);

这样程序就回提示你代码哪里的操作会导致堆损坏,比如越界等。虽然我试验提示的区域还是反汇编,但是从调试堆栈我找到了堆损坏的源头。看了差点没把我气死,这个错误在金山实习时就被BOSS指出来过,虽然当时我的代码并没有触发这个BUG。。。。

void SomeFunction(const char* str);

std::string str;
SomeFunction(str.c_str());

看似非常正常的一段代码,但是,显然,str.c_str()的生存期是由str管理的,一旦str销毁,c_str()也就销毁了,如果SomeFunction继续处理这个指针,那就不晓得损坏的是堆里面的哪块内存了,结果就是导致一系列诡异的BUG,让你很难找到错误的源头。所以,建议,使用string的c_str()函数时,需要非常谨慎。

发现经常DEBUG,有些问题还是很通用的,所以建立一个DEBUG标签,记录一些DEBUG经验。

你可能感兴趣的:(C/C++)