2011-11-18 61 views
47

首先,至少有4-5个主题与SO类似的主题。我读了他们每个人,我不觉得他们真的帮助我解决这个问题。如果有人发现重复的问题,我表示歉意。在发布之前,我已经完成了我的搜索工作,因为这似乎是一个非常常见的问题。如何正确替换全局新增&删除操作符

我使用Visual Studio .NET 2003在Windows 7

我有我自己的新/删除该点的过载,以我自己的自定义调用malloc()和free()用于诊断。我的新/删除重载是在一个头文件中,我已经包含在几个文件中。

问题是,代码基础是非常意大利面,并没有简单的方法来确保这些重载被一切使用。第三方库包含黑箱。我们也到处使用STL。

在我的测试中,我发现STL仍在将调用混合到我自己的新建/删除和标准MSVC新建/删除调用中。

将我的头文件包含在成千上万个其他文件中似乎不太实际,这只需要很长时间。任何人都可以提供一些关于如何正确有效地重载新的/删除全局的技巧,所以一切都使用我的定制内存管

+0

如果您在预编译的头应该涵盖最地面全局定义的运营商。或者,如果这用于检测内存泄漏,则可以使用CRT堆函数。 – AJG85

回答

63

这不是如何工作。你取代这两个运营商,而这是在链接时间完成的。你所需要做的就是编写一个单独的TU,定义这些运营商并将其链接到组合中。没有其他人永远需要了解这一点:

// optional_ops.cpp 

void * operator new(std::size_t n) throw(std::bad_alloc) 
{ 
    //... 
} 
void operator delete(void * p) throw() 
{ 
    //... 
} 

原则,没有必要对任何头文件来声明这些功能(operator newoperator delete),因为声明这两个函数已经硬编码到语言,如果你愿意。但是,std,std::bad_allocstd::size_t的名称是而不是预先声明的,所以您可能需要包含<new>或其他某个标头来提供这些名称。

在C++ 11及更高版本中,您可以使用decltype(sizeof(0))以不需要任何类型库的方式获取第一个参数的大小。 C++ 11也有一个更简单的异常模型,没有动态异常规范(最终在C++ 17中完全从语言中删除)。

void * operator new(decltype(sizeof(0)) n) noexcept(false) 
{ 
    //... 
} 
+1

连接器不会抱怨重复的定义吗?我认为ODR适用于此。更何况我们有120个DLL,我们必须在每个DLL项目中链接它。我想这比替代品更好。 –

+3

@RobertDailey:没有,特殊情况,标准,弱引用等等。我实际上在GCC上报告了一个关于这个问题的bug,所以最新版本甚至可以使用'-fwhole-program'和'-flto'和whatnot(见[这里](http://stackoverflow.com/questions/7629270/how-does-stdstring-allocate-memory-in-gcc-with-fwhole-program)和[here](http :?//gcc.gnu.org/bugzilla/show_bug.cgi ID = 50594)。)' –

+0

你能解释一下“标准覆盖”和“弱引用”是什么意思吗?谢谢!! –

31

而且加上这些行:

void *operator new[](std::size_t s) throw(std::bad_alloc) 
{ 
    // TODO: implement 
    return NULL; 
} 
void operator delete[](void *p) throw() 
{ 
    // TODO: implement 
}