2009-07-14 49 views
5

我試圖讓內存泄漏檢測與這兩篇文章的幫助工作: http://msdn.microsoft.com/en-us/library/e5ewb1h3%28VS.80%29.aspx http://support.microsoft.com/kb/q140858/內存泄漏檢測並覆蓋新的?

所以在我的stdafx.h我現在有:

#define _CRTDBG_MAP_ALLOC 
#include <stdlib.h> 
#include <crtdbg.h> 

#define new new(_NORMAL_BLOCK,__FILE__,__LINE__) 

唯一的問題是,我具有覆蓋新功能類:

class Dummy 
{  
    //overloaded new operator 
    void FAR* operator new(size_t cb); 
} 

現在,當我編譯這段代碼,我得到: 錯誤C2 059:語法錯誤:'常量' 錯誤C2091:函數返回函數

任何想法如何解決這個問題?

+0

這就是宏的問題:( – GManNickG 2009-07-14 22:38:31

+0

如果你不使用windows,我會建議valgrind。 – LiraNuna 2009-07-14 22:40:37

+0

如果我使用的是Windows,我會使用DUMA。 – EFraim 2009-07-14 22:42:43

回答

9

您可以使用pragma指令來保存和恢復重新啓用undefing時的新宏。參見[MSDN](http://msdn.microsoft.com/en-us/library/hsttss76(VS.71).aspx)的確切語法

#pragma push_macro("new") 
#undef new 
void FAR* operator new(size_t cb); 
#pragma pop_macro("new") 

你可以把這些標頭,如

begin_new_override.h:

#ifdef new 
#define NEW_WAS_DEFINED 
#pragma push_macro("new") 
#undef new 
#endif 

end_new_override.h:

#ifdef NEW_WAS_DEFINED 
#undef NEW_WAS_DEFINED 
#pragma pop_macro("new") 
#endif 

然後

#include "begin_new_override.h" 
void FAR* operator new(size_t cb); 
#include "end_new_override.h" 
+0

很酷,我不知道這是可能的:-) – 2015-12-08 23:36:31

1

嘗試 #undef new 類定義 前,然後後再次#define new new...

4

而是定義新的是不同的東西,爲什麼不超載運營商新的?

在全局命名空間的地方添加這些功能定義:

// operator new overloads 
void* operator new(const size_t size, const char* file, int line) throw(); 
void* operator new(const size_t size, const size_t align, const char* file, int line) throw(); 
void* operator new[](const size_t size, const char* file, int line) throw(); 
void* operator new[](const size_t size, const size_t align, const char* file, int line) throw(); 

// can't easily overload operator delete 
void operator delete(void* ptr) throw(); 
void operator delete[](void* ptr) throw(); 

// matched to the operator new overload above in case of exceptions thrown during allocation 
void operator delete(void* ptr, const char* file, int line) throw(); 
void operator delete[](void* ptr, const char* file, int line) throw(); 
void operator delete(void* ptr, const size_t align, const char* file, int line) throw(); 
void operator delete[](void* ptr, const size_t align, const char* file, int line) throw(); 

// global new/delete 
void* operator new(size_t size) throw(); 
void* operator new(size_t size, const std::nothrow_t&) throw(); 
void* operator new(size_t size, size_t align) throw(); 
void* operator new(size_t size, size_t align, const std::nothrow_t&) throw(); 

void* operator new[](size_t size) throw(); 
void* operator new[](size_t size, const std::nothrow_t&) throw(); 

void operator delete(void* ptr, const std::nothrow_t&) throw(); 
void operator delete[](void* ptr, const std::nothrow_t&) throw(); 

然後你可以定義自己的新宏這就要求通過對非全局版本和執行全球版本的斷言或警告,如果他們」重新召喚(捕捉任何滑過的東西)。

#define MY_NEW(s) new(s, __FILE__, __LINE__) 

如果您直接在課程上調用「新建」,則您的課程級重載將按預期工作。如果你想在課堂上給MY_NEW打電話,你可以,但是你必須重新定義班級中的超載以適應你的新課程。

4

在預處理器級別重新定義通過#definenew是在我的經驗是一個壞主意 - 你不但打破operator new過載,也放置new,以及其他可能的幾件事情。

將所有FILE和LINE宏擴展到處處,會導致您的.rodata和.data部分膨脹爲文件字符串和行號,並且每次調用都會生成更多的代碼。

好多了(如果更努力的前期),以利用調試信息的存在(例如.pdb文件),並使用類似DbgHelp庫的StackWalk64收集堆棧信息。

重載全局運算符new和運算符delete(array,nothrow等)的各種組合,讓它們在分配和釋放內存時存儲和釋放堆棧信息。

可以將此信息甚至存儲在像性病的結構::地圖<無效*,StackInfo >,只是要小心不要記錄引起地圖嵌入式allocs(全局鎖可能是足夠的單線程應用程序,多線程作爲練習留給讀者)。

既然你正在記錄整個堆棧的任何給定的分配,你可以做一些漂亮的樹分析,按「函數和後代」對分配(泄漏或其他)進行分組......這有時更容易追蹤複雜的泄漏如果你從他們的分配時間知道整個堆棧。