使用调试版本覆盖新版,而不会损坏放置新版

Overriding new with debug version without damaging placement new

本文关键字:新版 损坏 调试 版本 覆盖      更新时间:2023-10-16

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

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

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

那么,有没有办法在我们的代码中检测分配,而不会仅仅因为它们包含新的放置位置而拉入标头,而不必将上面的最后一个定义放在所有文件中或手动编写DEBUG_NEW?

#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")

我历史上解决这个问题的方法是使用预编译的标头,并做这样的事情(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__)   

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

我知道

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

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

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

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

这整个DEBUG_NEW的事情应该在火中死去!它只是勉强有用,在现代C++中根本没有用,因为你不再在理智C++中看到new

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

define new DEBUG_NEW行应该放在源文件中,毕竟是 #include 行。通过这种方式,它只应用于你自己的代码,而不是应用于任何其他h文件,如Boost。对DEBUG_NEW进行编辑的全局新内容可能会导致编译失败,应避免使用。