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);
}

现在当我编译这段代码时,我得到:错误 C2059:语法错误:'常量'错误 C2091:函数返回函数

知道如何解决这个问题吗?

4

4 回答 4

10

在为重载取消定义时,您可以使用 pragma 指令来保存和恢复新宏。有关确切语法,请参阅 [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"
于 2009-07-14T22:55:30.040 回答
4

与其将 new 定义为不同的东西,不如重载 operator 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,你可以,但你必须重新定义类中的重载以匹配你的新。

于 2009-07-14T23:01:06.767 回答
4

根据我的经验,在预处理器级别重新定义newvia#define是一个坏主意——你不仅会破坏operator new重载,还会破坏 place ,new可能还有其他一些东西。

让所有这些 FILE 和 LINE 宏到处扩展会导致您的 .rodata 和 .data 部分因文件字符串和行号而膨胀,并且每次调用都会生成更多代码。

.pdb利用调试信息(例如文件)的存在并使用DbgHelp库的StackWalk64之类的东西来收集堆栈信息要好得多(如果预先付出更多努力) 。

重载全局 operator new 和 operator delete 的各种组合(数组、nothrow 等),让它们在分配和释放内存时存储和释放堆栈信息。

您甚至可以将此信息存储在 std::map<void *, StackInfo> 之类的结构中,只是注意不要记录由映射插入引起的分配(对于单线程应用程序来说,全局锁可能就足够了,多-thread 留给读者作为练习)。

由于您正在为任何给定的分配记录整个堆栈,您可以进行一些漂亮的树分析,通过“函数和后代”对分配(泄漏或其他)进行分组......如果您知道有时更容易追踪复杂的泄漏整个堆栈从他们的分配时间。

于 2009-07-15T00:51:01.300 回答
1

在类定义之前尝试 #undef new ,然后在之后#define new new...再次尝试。

于 2009-07-14T22:41:20.567 回答