【问题标题】:Overriding new with debug version without damaging placement new用调试版本覆盖 new 而不会损坏放置 new
【发布时间】:2012-10-10 08:38:10
【问题描述】:

Microsoft 运行时库提供调试版本的分配函数。对于 C++,这是带有签名的 operator new 的调试变体:

void *operator new(size_t size, int blockType, const char *filename, int linenumber);

宏的定义如下

#define DEBUG_NEW new(_NORMAL_BLOCK, __FILE__, __LINE__)

现在要检测所有分配,通常定义一个

#if defined DEBUG_NEW
#define new DEBUG_NEW
#endif

但是这个定义破坏了任何使用placement new的地方,因为这两组参数最终是语法错误。现在我可以轻松处理我们代码中的少数用途,但标准库和 boost 使用新的布局。因此,全局定义它意味着在定义之前包含很多东西,这会减慢编译速度。

那么是否有任何方法可以在我们的代码中检测分配,而无需仅仅因为它们包含新的位置并且不必将上面的最后一个定义放在所有文件中或手动编写 DEBUG_NEW 就拉入标题?

【问题讨论】:

    标签: c++ visual-c++ c++03


    【解决方案1】:
    #pragma push_macro("new")
    #undef new
    
    new(pointer) my_class_t(arg1, arg2);
    
    #pragma pop_macro("new")
    

    #pragma push_macro("new")
    #undef new
    
    #include <...>
    #include <...>
    #include <...>
    
    #pragma pop_macro("new")
    

    【讨论】:

    • 描述push_macro()pop_macro() 的工作方式会很有帮助。比如,原来的newpop_macro("new")之后会恢复吗?
    【解决方案2】:

    我过去解决这个问题的方法是使用预编译的头文件,并执行类似的操作(StdAfx.h、Pch.h、PreCompiled.h 或其他):

    //First include all headers using placement new
    #include <boost/tuple/tuple.hpp>
    #include <vector>
    
    #define new MY_NEW
    #define MY_NEW new(__FILE__, __LINE__)   
    

    然后确保没有文件直接包含 boost 标头,而只有预编译的标头。

    【讨论】:

    • 在我们的情况下维护预编译的头文件真的很痛苦。由于各种可移植性问题,它们将非常庞大和复杂(代码库是为 4 个非常不同的平台编译的)。
    • 它们在哪些方面难以维护? pch 应该很少更改。
    • 如果它包含增强的东西,它会经常改变。但也许我应该尝试只预编译这个内存调试头(使用/Fi 编译器选项注入);新展示位置出现的位置要少得多。
    【解决方案3】:

    我知道这有点晚了,但这个问题可以通过使用模板魔法来解决。

    我最近一直在编写一个 debug_new 调试器,它添加了一个新关键字“placement”,它会在所有放置新调用之前写入。

    你可以在这里查看我的调试器:https://sourceforge.net/projects/debugnew/

    或来自 nvwa 的 debug_new 调试器:https://sourceforge.net/projects/nvwa/

    【讨论】:

      【解决方案4】:

      这整个 DEBUG_NEW 东西应该在火中消亡!它只是几乎没有用,而且在现代 C++ 中根本没有用,因为在正常的 C++ 中您不再看到 new

      有更好的选择,比如 DUMA,现在有了Dr. Memory(其工作方式类似于Valgrind,但在 Windows 上),使用 DEBUG_NEW 可憎绝对没有意义。

      【讨论】:

        【解决方案5】:

        define new DEBUG_NEW 行应该放在源文件中,毕竟 #include 行。通过这种方式,它仅适用于您自己的代码,而不适用于任何其他 h 文件,如 Boost。全局新的 DEBUG_NEW 重定义可能会导致编译失败,应该避免。

        【讨论】:

        • 你是对的,除了,你看,问题是明确不这样做
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2019-09-06
        • 1970-01-01
        • 2012-01-05
        • 1970-01-01
        • 1970-01-01
        • 2013-11-13
        • 1970-01-01
        相关资源
        最近更新 更多