【问题标题】:is the following new overload leaking memory?以下新的重载是否会泄漏内存?
【发布时间】:2012-05-20 03:02:33
【问题描述】:

我遇到过如下代码:

    class a {
    public:

        void *  operator new(size_t l, int nb);
        double  values;
    };
void *a::operator new (size_t l,int n)
{
    return new char[l+ (n>1 ? n - 1 : 0)*sizeof(double)];
}

据我所知,它被用于具有从“值”开始的类似数组的结构:

double* Val = &(p->a->values) + fColumnNumber;

我的问题是: 有内存泄漏吗?我对重载 new 运算符非常陌生,但我很确定分配的内存没有正确释放。这是否也意味着我永远无法在堆栈上创建“a”类?

谢谢

【问题讨论】:

  • 您显示的代码根本没有释放内存。显示这段代码,否则我们不能说内存是否泄漏。我没有看到怀疑内存泄漏的先验理由,除非operator delete 真的丢失了。
  • 不见了,这就是我所拥有的一切
  • 是的,无论如何,您都需要删除,无论是否重载运算符。是什么让你认为重载 new 会以某种方式工作?
  • 啊,这个问题更有趣了。
  • @KonradRudolph 为什么让这个问题更有趣?它现在恶化为一个简单的缺失析构函数问题,仅此而已。

标签: c++ memory-management operator-overloading new-operator


【解决方案1】:
  1. 您绝对可以在堆栈上创建“a”类。
  2. 您应该知道 4 个(实际上更多,但会坚持基础)新的和删除的方法签名。

    void* operator new (std::size_t size) throw (std::bad_alloc);
    void* operator new[] (std::size_t size) throw (std::bad_alloc);
    void operator delete (void* ptr) throw ();
    void operator delete[] (void* ptr) throw ();
    

    您正在“operator new”方法中分配一个数组,这应该在“operator new[]”方法中完成。这将摆脱你讨厌的检查。同时写“operator new”和“operator new[]”

  3. 不要忘记你想给调用者一个类型为“a”的对象(a myA = new a)所以确保你返回“a”而不是char*,因此你也需要进行强制转换。

  4. 需要编写相应的delete[]和delete方法。

  5. 为了回答您的问题,我相信它确实会泄漏内存。您提供的新签名称为“新位置”。这允许您在不分配内存的情况下分配一个新指针,而是给它一个指向的位置。示例:如果您需要指向内存中特定点的指针。

    long z = 0x0F9877F80078;
    a myA = new (z) a[5];  // 5 pointers that point to 0x0F9877F80078
    

根据定义,placement-new 运算符不应该分配内存,因为你有你让你泄漏。摆脱你的第二个参数,你现在可以这样做,因为你有两个版本的 operator new 并且你很高兴。不要忘记返回一个对象“a”。

查看 IBM 信息中心: http://publib.boulder.ibm.com/infocenter/comphelp/v8v101/index.jsp?topic=%2Fcom.ibm.xlcpp8a.doc%2Flanguage%2Fref%2Fcplr318.htm

以及参考资料,cpluplus.com: http://www.cplusplus.com/reference/std/new

【讨论】:

    【解决方案2】:

    我相信它在技术上会按原样产生 UB,尽管它是一种可能永远不会引起可见副作用的 UB(它使用 new [],但我相信它会与 delete 匹配——但对于char,这通常不会导致明显的问题)。

    IMO,它使用新表达式来分配真正应该是原始字节而不是对象的内容几乎更糟糕。如果我这样做,我会这样写:

    void *a::operator new (size_t l,int n)
    {
        return ::operator new(l+ (n>1 ? n - 1 : 0)*sizeof(double));
    }
    

    你会匹配到:

    void a::operator delete(void *block)
    {
        ::operator delete(block);
    }
    

    【讨论】:

    • +1 指出 UB 不会伤害任何人并且是一个不错的选择。
    • @lezebulon:主要是如果你有一个operator new,你应该有一个匹配的operator delete,如果只是为了让你清楚你所拥有的是正确的,并且你没有忘记一些东西.
    • 谢谢你的回答,我担心的是调用delete时只会释放sizeof(a)字节。我仍然不太确定为什么所有分配的内存都会被释放
    【解决方案3】:

    它很好,但是你需要在使用这个类的代码中使用delete[],而不是delete,因为它分配一个数组。请注意,用户不会得到他们需要执行此操作的任何提示 - 因此为他们重载删除运算符将是一个好主意。

    【讨论】:

      【解决方案4】:

      我不明白为什么在 a * 上调用的默认 operator delete 无法正确释放此自定义 operator new 分配的内存。最好的检查方法是实际编写一些代码并找出答案,尽管我可能会在 valgrind 等分析器中运行它而不是 rob05c 的技术。我假设提问者看到发生了内存泄漏并怀疑这是原因,所以围绕这个运算符编写一个测试用例似乎是一项值得的努力。

      如果事后没有人真正删除它,它显然会泄漏......

      我会质疑是否有必要为这种功能覆盖 new,但我也认为这是其他人的代码。

      【讨论】:

        【解决方案5】:

        这很容易找到。编写一个构造和解构大量 a 的循环,并观察你的内存使用情况。如果它泄漏,它会很快上升。

        【讨论】:

        • 这几乎没有告诉你什么,因为标准没有指定实现如何跟踪内存。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-03-06
        • 1970-01-01
        • 2010-09-13
        • 1970-01-01
        • 1970-01-01
        • 2020-04-14
        相关资源
        最近更新 更多