MFC和使用Std的dll之间的内存泄露误报情况

From: http://blog.sina.com.cn/s/blog_4087d260010090sf.html


最近搞一个Delta3D的工程,因为牵扯到要放在MFC中,所以费了牛劲才找到放到MFC中的方法,结果还未等高兴,就发现了内部泄漏,泄漏的地方是dtCore.dll,这个DLL是静态关联的DLL,所以我看了看泄漏的具体对象,发现都和std之流相关,于是极度怀疑是std这个家伙作祟,这些东西的怪脾气老多了~
 
上网一查,果然如我所料,正是由于MFC和std的某些不兼容导致的。
特此粘贴原文如下
 
一种MFC内存泄露误报的情况        

一.环境

操作系统:Windows2003 server

IDE:vs2003

二.现象

新建一个dll的空项目,加入mydll.h和mydll.cpp两个文件,内容如下:

// mydll.h

#ifndef _MYDLL_H_

#define _MYDLL_H_

__declspec( dllexport ) void VoidFunc();

#endif

// mydll.cpp

#include "mydll.h"

#include <string>

const std::string description = "Dll:this is my dll";

void VoidFunc()

{

    const std::string teststr = "Func:VoidFunc string";

}

采用“多线程调试 DLL”编译,生成mydll.dll和mydll.lib。

新建一个MFC工程,使用“在共享 DLL 中使用 MFC”,导入mydll.lib,可在某处(例如OnButtonClick等)调用VoidFunc。使用DEBUG版本编译运行,在窗口退出时在IDE的输出窗口可看到:

Detected memory leaks!

Dumping objects ->

{112} normal block at 0x00365C78, 32 bytes long.

Data: <Dll:this is my d> 44 6C 6C 3A 74 68 69 73 20 69 73 20 6D 79 20 64

Object dump complete.

很明显,输出表明有内存泄漏。

三.分析

根据IDE输出内容看,在内存地址为0x00365C78有32字节的内存泄漏,内容为:Dll:this is my d...,从内容可以看出,这是mydll中全局string变量description的值。

MFC在DEBUG版本中使用_malloc_dbg和_free_dbg进行分配和释放内存,__malloc_dbg将调用_heap_alloc_dbg进行内存分配,它将一些附加信息(大部分就是dump出来的信息)放在分配内存的前面(其实后面也有),所有分配的内存组成一个双向链表。相应的,_free_dbg将释放内存同时在链表中删除该节点。程序退出之前MFC检查这个链表就可查出内存泄漏情况。这里的细节可查看CRT源码的dbgheap.c文件。

同样,vc71携带的std::string实现的DEBUG版本也是使用_malloc_dbg和_free_dbg进行分配和释放内存,因此MFC是可以跟踪到mydll的内存分配的。难道dll的全局变量description确实没有释放内存吗?

在std::string::~string处设置断点调试,发现description有释放内存,MFC却报内存泄漏,这是怎么回事?

想起MFC是使用CRT函数_CrtDumpMemoryLeaks(dbgheap.c)来报告内存泄漏的,在该处设置断点,在调用堆栈回溯函数调用,发现是函数_DllMainCRTStartup被调用,该函数的参数dwReason为DLL_PROCESS_DETACH,表示这是在卸载mfc71d.dll,继续运行,程序停在std::string::~string断点处,跟踪可知这是字符串变量description。由此可说明:由于mfc71d.dll在my.dll的全局变量释放之前被卸载导致输出内存泄漏报告,但实际上并没有内存泄漏。可将VoidFunc函数中的teststr变量改为static,也可看到报告该变量内存泄漏。

四.结论

由于mfc71d.dll在其他动态库卸载之前被卸载导致输出内存泄漏报告,但实际上并没有内存泄漏。

五.也许没有结束

mfc71d.dll为什么在my.dll的全局变量释放之前(也就是在my.dll卸载之前)被卸载?隐式链接的动态库的卸载顺序的依据是什么,根据代码调用方式还是动态库依赖关系,还是其他什么?


你可能感兴趣的:(MFC和使用Std的dll之间的内存泄露误报情况)