如何正确替换全局new和delete运算符

voi*_*ter 57 c++ windows memory-management visual-studio-2003

首先,至少有4-5个主题在SO上有类似的主题.我读了他们每个人,我觉得他们真的没有帮我解决这个具体问题.如果其他人发现重复的问题,我道歉.在我发布之前,我已经完成了我的搜索工作,因为它似乎是一个非常常见的问题.

我在Windows 7上使用Visual Studio .NET 2003.

我有自己的new/delete重载,指向我自己的malloc()和free()的自定义调用.我的新/删除重载在一个头文件中,我已经包含在几个文件中.

问题是,代码库几乎是意大利面,没有简单的方法可以确保所有东西都能使用这些重载.包括第三方库是黑盒子.我们到处都使用STL.

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

将我的头文件包含在数千个其他文件中似乎不太现实,这需要花费太长时间.任何人都可以提供一些关于如何正确有效地重载新/全局删除所以一切都使用我的自定义内存管理器的技巧?

Ker*_* SB 77

这不是这个工作原理.您替换了两个运算符,这是在链接时完成的.您需要做的就是编写一个定义这些运算符的TU 并将其链接到混合中.没有人需要知道这件事:

// optional_ops.cpp

void * operator new(std::size_t n) throw(std::bad_alloc)
{
  //...
}
void operator delete(void * p) throw()
{
  //...
}
Run Code Online (Sandbox Code Playgroud)

原则上,不需要任何头文件来声明这些函数(operator new,operator 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)
{
  //...
}
Run Code Online (Sandbox Code Playgroud)

  • @RobertDailey:该标准涵盖用户定义*替换*函数,因此不存在违反ODR的情况.编译器*通过使标准函数"弱"引用实现*this,如果找到另一个相同名称的符号,则链接器将覆盖这些引用. (7认同)
  • 是的,在Windows上,你无法为整个程序提供替换的新/删除功能,而无需将它们链接到每个DLL中.或者至少强制dll导入这些函数,但我不确定它是否有效.我认为DLL以这种方式工作是不幸的.在其他平台上,当程序启动时链接共享库时,它们通常遵循与静态链接的翻译单元相同的规则,因此如果您的程序替换新的/删除,则共享库也将获得这些替换. (4认同)
  • 你可能还想覆盖`new`的"no throw"版本,它有第二个参数`const std :: nothrow_t&`(C++标准的一部分) (4认同)
  • @RobertDailey:没有,特殊情况,标准,弱引用等等.我实际上在GCC报告了一个关于这个的错误,所以最新版本甚至可以使用`-fwhole-program`和` -flto`和诸如此处(见[here](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).)` (3认同)

小智 34

还添加以下行:

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