今天遇到C语言的malloc free失败问题,因为工程代码量巨大,定位了半天才发现是DLL的问题,动态链接库里malloc分配的内存,到主程序中free时崩溃失败。起初以为是指针越界好或被修改,后来直接改成申请后就free,直接失败,于是就怀疑是DLL与主程序之间的调用问题。于是总结一下常见失败问题方便后来者参考。
该free错误非常容易定位,也就是一个指针没有成功执行malloc分配,就直接free肯定会失败,因为该指针还未经过初始化。例如:
1 |
void main() { |
2 |
int * pBuf = NULL; |
3 |
free (pBuf); |
4 |
} |
这个free错误则不好查找,因为实际的程序往往没下面的例子这么简单,可能从申请到最后释放跨域多个模块、大量的处理代码逻辑,指针初始值被修改掉,也就是说分配的这段内存的“门牌号”被改掉了,那么free就会失败。
1 |
void main() { |
2 |
int * pBuf = ( int *) malloc (250); |
3 |
pBuf++; |
4 |
free (pBuf); |
5 |
} |
模块之间的分配和释放分离设计,从设计上就是有问题的(至少天缘是如此认为),一般对于此类分享,最好使用共享内存方式,也就是说,分配和释放均由同一方管理,尽管我们有办法让他们实现分配和释放任务分离。
解决办法:
1、如果可以改成LIB库进行静态链接,可以改成LIB调用方式。
2、如果坚持使用DLL调用,可以考虑给DLL里添加一个专门用于释放该内存的函数,以便主程序调用。
3、使用可在全局堆分配内存的函数(比如HeapAlloc(GetProcessHeap(),0,size)、HeapFree(GetProcessHeap(),0,p)等等),不过不建议使用,最好还是从架构上调整一下。
比如主程序Project->Setting->C/C++的Use Run-time liberary设置为Debug Multithreaded DLL,而模块的User Run-time liberary设置为Debug Multithreaded的话,主程序调用释放free 通过DLL malloc的指针就会失败,其实这时,如果继续运行的话,delete DLL生成对象也是失败的。但是统一成Debug Multithreaded DLL就没有问题。具体可参考:error LNK2005: "public: void __thiscall 一文。