我试图在这两篇文章的帮助下进行内存泄漏检测: 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);
}
现在当我编译这段代码时,我得到: 错误C2059:语法错误:'常量' 错误C2091:函数返回函数
知道如何解决这个问题吗?
答案 0 :(得分:10)
您可以使用pragma指令在取消过载时保存和恢复新宏。有关确切的语法,请参阅[MSDN](http://msdn.microsoft.com/en-us/library/hsttss76(VS.71).aspx)。
E.g。
#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"
答案 1 :(得分:4)
为什么不重载operator new?而不是将new定义为不同的东西?
在全局命名空间的某处添加这些函数定义:
// 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__)
如果直接在类上调用“new”,您的类级重载将按预期工作。如果你想在课堂上打电话给MY_NEW,你可以,但你必须重新定义课程中的重载以匹配你的新课程。
答案 2 :(得分:4)
根据我的经验,在预处理器级别通过new
重新定义#define
是一个糟糕的主意 - 您不仅要打破operator new
重载,还要放置new
,并且可能其他一些事情。
让所有那些FILE和LINE宏扩展到任何地方会导致.rodata和.data部分膨胀文件字符串和行号,并且每次调用生成更多代码。
更好(如果需要更多努力)利用调试信息(例如.pdb
文件)的存在并使用类似DbgHelp
库的StackWalk64之类的东西来收集堆栈资讯
重载全局operator new和operator delete(array,nothrow等)的各种组合,让它们在分配和释放内存时存储和释放堆栈信息。
您甚至可以将此信息存储在类似std :: map&lt; void *,StackInfo&gt;的结构中,只需注意不要记录由地图插入引起的alloc(对于单线程,全局锁可能就足够了) app,多线程留给读者练习。)
由于您正在为任何给定的alloc记录整个堆栈,您可以进行一些漂亮的树分析,通过“函数和后代”对分配(泄漏或其他)进行分组......有时,如果跟踪复杂的泄漏,则更容易你知道整个堆栈的分配时间。
答案 3 :(得分:1)
尝试
#undef new
在课前定义
然后再次#define new new...
。