VC内存溢出一例 –- 调用约定不一致

这个是网查的跟我在做图像分割realse相反的情况;

最近在写一个程序,调用了多个DLL,每个DLL代码都支持多线程,Debug的模式下基本调通了,但是在Release模式下,程序因为内存溢出而崩溃,中断在gs_report.c文件的298行位置(_CRT_DEBUGGER_HOOK(_CRT_DEBUGGER_GSFAILURE),如下图:
     

     由于问题是出自某个DLL模块中,并且是多线程的,并且出现中断的断点无法回溯,很难直接定位到是哪个DLL模块的问题。在将一个一个模块被调用的代码注释后,大概确定了可能出问题的模块,以及可能的函数。由于是Release版本的问题,无法设置断点,只好用输出到Output窗口的方式调试,想进一步确定出现内存溢出的代码段。折腾了很长时间,一直没找到问题根源。

     网上搜索了一下,有人是Debug版本有这样的内存溢出错误,Release版本没有,是因为字符串填充的时候超过的申请的长度,和本例的情况不一样。开始我也觉得可能是哪个DLL库字符串操作问题,仔细检查了一些,没有发现问题。

     后来在测试一个作为参数传输到某个DLL中函数的字符串的时候,发现此字符串在被调用函数之后内容被改变了,而理论上被调用的函数是不改变此字符串的内容。调试了一下,发现此字符串在被调用的函数最后返回之前还是正常的,函数返回之后就不对了,也就是说函数退出之后的出栈操作有问题,不是按入栈完全相反的动作操作的。产生这个问题的原因有可能是函数的声明不对,也就是在DLL中的声明和在主程序中的声明不一致。检查了一下参数和返回值类型,是完全一致的。那会是哪不一样呢?

     DLL中的声明: EXPORTDLL unsigned int MyFunction(char * appname);
     主函数中的声明: typedef unsigned int (WINAPI *lpMyFunction)(char* appname);
     在VC中,EXPORTDLL定义为: #define EXPORTDLL extern “C” __declspec (dlexport); WINAPI定义为:#define WINAPI __stdcall ;回想起以前解决过的一些问题,在给回调函数传函数指针时,就为是用__stdcall还是__cdcall折腾过,所以估计这里可能是函数约定调用不一致导致的,正好和前面函数参数值被非法改变有关系。WINAPI这个调用约定是没法改的,那就修改DLL的函数。将DLL项目 Configuration Properties --> C/C++ --> Advanced --> Calling Convention设置从默认的__cdecl(/Gd)改为 __stdcall(/Gz),重新编译,重新运行,一切正常。

我的:

  恰好相反,release没问题,debug就出问题。

原文地址:https://www.cnblogs.com/pengkunfan/p/exception.html