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卸載之前)被卸載?隱式鏈接的動態庫的卸載順序的依據是什麼,根據代碼調用方式還是動態庫依賴關係,還是其他什麼?


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章