内存泄漏检测并覆盖新的?

时间:2022-11-17 07:30:19

I am attempting to get Memory leak detection working with the help of these two articles: http://msdn.microsoft.com/en-us/library/e5ewb1h3%28VS.80%29.aspx http://support.microsoft.com/kb/q140858/

我试图在这两篇文章的帮助下进行内存泄漏检测:http://msdn.microsoft.com/en-us/library/e5ewb1h3%28VS.80%29.aspx http://support.microsoft。 COM / KB / q140858 /

So in my stdafx.h I now have:

所以在我的stdafx.h中我现在有:

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

#define new new(_NORMAL_BLOCK,__FILE__,__LINE__)

The only problem is, I have a class which overrides the new function:

唯一的问题是,我有一个覆盖新函数的类:

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

Now when I compile this code, I get: error C2059: syntax error : 'constant' error C2091: function returns function

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

Any idea how I can fix this?

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

4 个解决方案

#1


You can use pragma directives to save and restore the new macro when undefing for overloads. See [MSDN](http://msdn.microsoft.com/en-us/library/hsttss76(VS.71).aspx) for the exact syntax.

您可以使用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") 

You can put these in headers, e.g.

你可以把这些放在标题中,例如

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

And then

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

#2


Redefining new via #define at the preprocessor level is a bad idea in my experience -- you not only break operator new overloads, but also placement new, and probably a few other things.

根据我的经验,在预处理器级别重新定义新的#define是一个坏主意 - 你不仅要打破运营商新的重载,还要放置新的,以及其他一些东西。

Having all those FILE and LINE macros expanding everywhere causes your .rodata and .data sections to bloat with file strings and line numbers, and generates much more code per call.

让所有那些FILE和LINE宏扩展到任何地方会导致.rodata和.data部分膨胀文件字符串和行号,并且每次调用生成更多代码。

Much better (if more effort up-front) to take advantage of the existence of debug information (e.g. .pdb file) and use something like the DbgHelp library's StackWalk64 to gather stack info.

更好(如果需要更多努力)利用调试信息(例如.pdb文件)的存在并使用类似DbgHelp库的StackWalk64来收集堆栈信息。

Overload the various combinations of global operator new and operator delete (array, nothrow, etc), have them store and release stack information as memory is allocated and freed.

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

You can even store this information in a structure like a std::map<void *, StackInfo>, just be careful to not record the allocs caused by the map inserts (a global lock may be sufficient for a single-threaded app, multi-threaded is left as an exercise to the reader).

您甚至可以将此信息存储在std :: map 之类的结构中,只需注意不要记录由地图插入引起的alloc(全局锁可能足以用于单线程应用程序,多 - 线程留给读者练习)。

Since you're recording the entire stack for any given alloc, you can do some nifty tree analysis, grouping allocations (leaks or otherwise) by "function and descendants"... And it is sometimes easier to trace complicated leaks if you know the entire stack from their allocation time.

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

#3


Instead of defining new to be something different, why not overload operator new?

而不是将new定义为不同的东西,为什么不重载operator new?

Add these function definitions somewhere in the global namespace:

在全局命名空间中的某处添加这些函数定义:

// 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();

Then you can define your own new macro which calls through to the non-global versions and implement the global versions to assert or warn if they're called (to catch anything slipping through).

然后,您可以定义自己的新宏,该宏调用非全局版本并实现全局版本以断言或警告它们是否被调用(以捕获任何滑动)。

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

Your class-level overloads will work as expected if you call 'new' directly on the class. If you want to call MY_NEW on the class, you can but you'll have to redefine the overload in the class to match your new.

如果直接在类上调用“new”,则类级别的重载将按预期工作。如果你想在课堂上调用MY_NEW,你可以但你必须重新定义课程中的重载以匹配你的新课程。

#4


Try #undef new before class definition and then #define new new... again after.

在课程定义之前尝试#undef new,然后再尝试#define new new ...

#1


You can use pragma directives to save and restore the new macro when undefing for overloads. See [MSDN](http://msdn.microsoft.com/en-us/library/hsttss76(VS.71).aspx) for the exact syntax.

您可以使用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") 

You can put these in headers, e.g.

你可以把这些放在标题中,例如

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

And then

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

#2


Redefining new via #define at the preprocessor level is a bad idea in my experience -- you not only break operator new overloads, but also placement new, and probably a few other things.

根据我的经验,在预处理器级别重新定义新的#define是一个坏主意 - 你不仅要打破运营商新的重载,还要放置新的,以及其他一些东西。

Having all those FILE and LINE macros expanding everywhere causes your .rodata and .data sections to bloat with file strings and line numbers, and generates much more code per call.

让所有那些FILE和LINE宏扩展到任何地方会导致.rodata和.data部分膨胀文件字符串和行号,并且每次调用生成更多代码。

Much better (if more effort up-front) to take advantage of the existence of debug information (e.g. .pdb file) and use something like the DbgHelp library's StackWalk64 to gather stack info.

更好(如果需要更多努力)利用调试信息(例如.pdb文件)的存在并使用类似DbgHelp库的StackWalk64来收集堆栈信息。

Overload the various combinations of global operator new and operator delete (array, nothrow, etc), have them store and release stack information as memory is allocated and freed.

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

You can even store this information in a structure like a std::map<void *, StackInfo>, just be careful to not record the allocs caused by the map inserts (a global lock may be sufficient for a single-threaded app, multi-threaded is left as an exercise to the reader).

您甚至可以将此信息存储在std :: map 之类的结构中,只需注意不要记录由地图插入引起的alloc(全局锁可能足以用于单线程应用程序,多 - 线程留给读者练习)。

Since you're recording the entire stack for any given alloc, you can do some nifty tree analysis, grouping allocations (leaks or otherwise) by "function and descendants"... And it is sometimes easier to trace complicated leaks if you know the entire stack from their allocation time.

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

#3


Instead of defining new to be something different, why not overload operator new?

而不是将new定义为不同的东西,为什么不重载operator new?

Add these function definitions somewhere in the global namespace:

在全局命名空间中的某处添加这些函数定义:

// 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();

Then you can define your own new macro which calls through to the non-global versions and implement the global versions to assert or warn if they're called (to catch anything slipping through).

然后,您可以定义自己的新宏,该宏调用非全局版本并实现全局版本以断言或警告它们是否被调用(以捕获任何滑动)。

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

Your class-level overloads will work as expected if you call 'new' directly on the class. If you want to call MY_NEW on the class, you can but you'll have to redefine the overload in the class to match your new.

如果直接在类上调用“new”,则类级别的重载将按预期工作。如果你想在课堂上调用MY_NEW,你可以但你必须重新定义课程中的重载以匹配你的新课程。

#4


Try #undef new before class definition and then #define new new... again after.

在课程定义之前尝试#undef new,然后再尝试#define new new ...