重载新/删除

Bra*_*mie 24 c++ operator-overloading new-operator delete-operator

我在我的程序中制作了一个小内存泄漏查找程序,但我的方法是重载new和delete(以及new []和delete [])似乎没有做任何事情.

void* operator new (unsigned int size, const char* filename, int line)
{
    void* ptr = new void[size];
    memleakfinder.AddTrack(ptr,size,filename,line);
    return ptr;
}
Run Code Online (Sandbox Code Playgroud)

我重载的方式new显示在上面的代码片段中.我想这是操作员返回void*的东西,但我不知道该怎么办.

Dan*_*Dan 140

回覆:

永远不要尝试全局重载新/删除

为什么每当有人尝试使用C++不那么常见的功能时,有人会表现得不应该这么做?

它一直都在做,这很常见,而且我没有为不这样做的公司工作过.

全局重载的new和delete非常有助于跟踪内存,内存错误,缓冲区溢出等.

在他们正确的思想中,没有人会通过一个包含数百万行代码的程序,并为每个类添加一个新的删除成员.那只是愚蠢的.

  • "为什么每当有人试图使用不那么常见的C++特性时,有人表现得不应该这么做?" 我发现这是一个没有经验的人的膝盖反应.例如,他们在一些博客文章中读到使用原始指针是不好的,使用智能指针会让你很酷.所以任何人使用原始指针(即使它们必须由于系统的硬件限制)都是错误的. (37认同)
  • 许多游戏引擎也会覆盖全局新增和删除 (10认同)

kyk*_*yku 51

也许你可以通过一些预处理器魔术来做你想做的事:

#include <iostream>

using namespace std;

void* operator new (size_t size, const char* filename, int line) {
    void* ptr = new char[size];
    cout << "size = " << size << " filename = " << filename << " line = " << line << endl;
    return ptr;
}

#define new new(__FILE__, __LINE__)

int main() {
    int* x = new int;
}
Run Code Online (Sandbox Code Playgroud)

  • 应该是`size_t`而不是`unsigned int`?我相信在某些平台上这些类型并不相同. (3认同)

T.E*_*.D. 12

我认为这里的问题是你的新参数配置文件与标准运算符new的参数配置文件不匹配,因此一个不会被隐藏(因此仍然被使用).

new和delete的参数配置文件需要如下所示:

void* operator new(size_t);
void operator delete(void*, size_t);
Run Code Online (Sandbox Code Playgroud)


dir*_*tly 6

void* ptr = new void[size];
Run Code Online (Sandbox Code Playgroud)

不能这样做.修理它.

永远不要尝试全局重载新/删除.要么将它们放在基类中,要从此类派生所有对象,要么使用命名空间或模板分配器参数.为什么,你可能会问.因为如果你的程序不只是一个文件而且使用STL或其他库,你就会搞砸了.

这是newVS2005 的蒸馏版操作员new.cpp:

void * operator new(size_t size) _THROW1(_STD bad_alloc)
{       // try to allocate size bytes
   void *p;
   while ((p = malloc(size)) == 0)
    if (_callnewh(size) == 0)
     {       // report no memory
        static const std::bad_alloc nomem;
        _RAISE(nomem);
     }

     return (p);
}
Run Code Online (Sandbox Code Playgroud)

  • 实际上,我有充分的理由这样做过一次.我们有一个编译器"问题",它在DLL边界以不安全的方式使用堆.解决方法是创建一个使用特定命名堆的"new"自定义版本. (7认同)
  • 如果您不尝试释放未分配的内存(反之亦然),那么库和其他所有内容都不会出现问题.STL可以使用自定义内存分配器.我们在调试版本中长时间使用自定义新建/删除操作符并且没有问题. (5认同)
  • "你为什么不提出错误,而是选择玩火?" 如果您不得不与供应商合作,您就会知道该问题的答案.有些人比其他人好,有些人只会说"感谢错误报告 - 它将在下一个版本中修复 - 哦你的许可证不包括下一个版本的方式......"有些人甚至可能会这样做如@TED所说,"这不是一个错误,它是一个特征" (5认同)
  • 您为什么不提交错误,而是选择玩火? (2认同)
  • 我们做到了。我们得到的答复是“DLL 在我们的系统中不能很好地跨进程工作”。我们最终停止使用它们,但在短期内解决了问题。 (2认同)