代码之家  ›  专栏  ›  技术社区  ›  Kyle

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

  •  5
  • Kyle  · 技术社区  · 16 年前

    我正试图借助这两篇文章进行内存泄漏检测: 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 回复  |  直到 12 年前
        1
  •  9
  •   Logan Capaldo    16 年前

    取消重载时,可以使用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") 
    

    你可以把这些放在头上,例如

    开始_new_override.h:

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

    结束新的覆盖.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"
    
        2
  •  4
  •   leander    16 年前

    重新定义 new 通过 #define 根据我的经验,在预处理器级别是一个坏主意——你不仅会破坏 operator new 重载,但也放置 新的 可能还有其他一些事情。

    所有这些文件和行宏在任何地方展开都会导致.rodata和.data节膨胀,其中包含文件字符串和行号,并在每次调用时生成更多的代码。

    更好的方法是(如果预先做更多的努力)利用调试信息的存在(例如 .pdb 文件)并使用类似 DbgHelp 图书馆的 StackWalk64 收集堆栈信息。

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

    您甚至可以将这些信息存储在一个结构中,如std::map<void*,stackinfo>,只需注意不要记录由映射插入引起的分配(全局锁可能足够用于单线程应用程序,多线程留给读者作为练习)。

    由于您正在为任何给定的alloc记录整个堆栈,所以您可以进行一些漂亮的树分析,按“函数和子体”对分配(泄漏或其他)进行分组…如果您从分配时间了解整个堆栈,那么跟踪复杂的泄漏有时会更容易。

        3
  •  4
  •   dma    12 年前

    为什么不将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,你可以,但是你必须重新定义类中的重载来匹配你的new。

        4
  •  1
  •   EFraim    16 年前

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