1、 问题描述
XP环境VS2008平台下自己写了一个DLL,然后在另外一个工程里调用了这个DLL,程序的Debug版本在XP下和Win7(装有VS2008)下可以运行,Release版本在XP下可以运行,但是在Win7下运行程序奔溃。
问题事件名称: APPCRASH
应用程序名: test.exe
应用程序版本: 1.0.0.1
应用程序时间戳: 53853a0f
故障模块名称: ntdll.dll
故障模块版本: 6.1.7601.17725
故障模块时间戳: 4ec49b8f
异常代码: c0000005
异常偏移: 000332a0
2、问题发现
刚开始以为是程序发布平台设置的问题,因为使用的Win7是64位的,所以拼命的在网上搜索如何让32位程序在64位的系统下运行,方向不对,没有收获,突发奇想,是不是这台电脑系统有问题,然后用另外一台32位的Win7测试程序,结果程序还是奔溃了,这说明程序在win7环境下运行都失败,经过在Win7下调试,发现每次调用完DLL里面的一个函数就会出现内存释放出错,vector<CString> FunctionTest(param1,param2)然后我将函数里的内容全部注释重新编译DLL和程序发现还是有内存释放出错,最终发现问题所在:内存释放一定要遵从哪里开辟哪里释放的原则,比如说在DLL中开辟的内存就需要在DLL中释放,否则出错。
3、原因分析
因为在DLL函数中使用了Vector中pushback函数(次数比较多),使得vector内存重新分配,然后函数调用完后,vector值被传递到主程序exe里,操作结束后vector释放操作在exe中进行,所以导致程序奔溃。
4、 网上解决方案
a、 如果知道DLL中vector改变的大小,可以提前手动分配好大小(Resize),这样避免vector重新分配内存。
b、 传递vector指针
c、 传递const vector<TYPE>(这种方法不符合我这里,因为我要改变vector里值)
d、 在DLL中提供内存释放接口,手动调用释放内存函数释放内存,这样就保证了在DLL中开辟的内存在DLL中释放。(这个方案在其他例子中可行)
e、 在DLL类中声明一个Vector变量,返回值用该变量的引用(这个方法很棒,是前辈介绍的) 函数原型改为
vector<CString> & FunctionTest(param1,param2);
采用引用的形式在函数返回时不会产生内存分配操作,而且DLL中vector内存变化最终由DLL类来管理,不用程序员担心。
5、 延伸
如果是参数里面有vector也会造成程序奔溃,因为在参数传递过程中DLL中开辟了内存,解决的办法也可以采用传递引用参数的形式,而且如果参数在执行过程中不会被改变可以用const修饰如:
vector<CString> & Function(vector<CString> & param1, const CString ¶m2);
至于为什么这样写,就自己多想想吧,还有一个问题就是为什么Release的程序在XP下运行没有提示任何问题,我能想到的是Win7内存优化比XP好,在XP中可能造成了内存泄露,希望有人指出真正的原因! /yh
本文原创,本文固定链接: http://www.qiezichaodan.com/programs_crash/