【问题标题】:Bypass override of operator new in C++在 C++ 中绕过运算符 new 的覆盖
【发布时间】:2013-05-08 12:40:47
【问题描述】:

有没有办法绕过operator new 的覆盖?

类似这样的:

void* ::operator new( std::size_t size ) {
    void *p = ( ::operator new( size ) );  // But original, _not_ infinite recursion
    // do stuff with p
    return p; 
}

背景: 我有一些遗留代码,我们最近切换到使用 Visual Studio 2012 进行编译。现在,当malloc 无法使用足够的内存块时,我们会随机崩溃。 (是的,代码到处都是小内存泄漏和其他不良行为。但不幸的是,彻底清理是不现实的,它大约是 500 000 SLOC。)

我目前的理论是,原因是几乎所有源文件都包含一个带有以下operator new 覆盖的标题:

void* ::operator new( std::size_t size ) {
    void* p = malloc( size );
    if( p == NULL )
        throw;
    // set memory to zero
    memset( p, 0, size );
    return p;
};

void* ::operator new[]( size_t count ) throw(std::bad_alloc) {
    // try to allocate count bytes for an array
    return (operator new(count));
}

delete 没有覆盖。

本质上,这意味着应用程序将使用malloc 的分配与使用delete 而不是free 的释放混合在一起。

首先尝试 Q&D 修复: 引入使用 freedelete 覆盖。但这只是部分帮助,因为有时包含订单和链接库仍然会搞砸。

第二次尝试 Q&D 修复: 删除覆盖。但不幸的是,将内存初始化为 0 是必要的。使用的旧编译器的遗产,它总是这样做,而假设 C++ 的编码器总是会这样做。

我知道 new() 会解决这个问题,但不幸的是,我不知道有什么好的方法可以在不手动检查所有源代码并更新它的情况下使用它。它也无助于实现不佳的类,这些类假定其所有成员在构造函数中没有这样做的情况下都被取消。

因此,我对 Q&D 修复的第三个想法: 正如这个问题所询问的那样,在覆盖中使用正常的 new 。

【问题讨论】:

  • 在运算符 new 上使用 =delete。 8.4.3 标准的删除定义\可能会提供更多细节。
  • 无论如何,您的全局operator new 很可能以malloc 的形式实现(否则您在第一次调用delete 时会崩溃)。所以这个覆盖唯一不同的是零填充内存。做你想做的事不太可能有帮助(即使有可能),因为当前版本已经做了完全相同的事情。为delete 添加覆盖不太可能有帮助,因为当前版本已经做了完全相同的事情(尽管为了保持一致性我还是会这样做)。 你需要修复真正的内存错误。没有办法解决这个问题。
  • @n.m.,感谢您的评论。我检查了 Visual Studio 中包含的源文件,在我看来,operator new 没有在 MS C++ 中使用malloc 实现。 mallocoperator new 都是用 _heap_alloc 实现的,但在我理解的一些簿记方面有所不同。
  • 因此您需要将覆盖从标题中移出并放入适当的源文件中,并为delete 添加覆盖。世界上没有任何理由会搞砸任何事情。如果是这样,你需要解决这个问题,因为谁知道它会在哪里损害你的项目。

标签: c++ operator-overloading new-operator visual-c++-2012


【解决方案1】:

有没有办法绕过 operator new 的覆盖?

我不知道,但是你为什么不简单地在你的自定义函数中重新实现它,就像 MS 在他们的基于 _heap_alloc 的实现中所做的那样,然后添加你的自定义呢?

一个生死攸关的分配尝试无论如何都不是 MS 所做的:

http://msdn.microsoft.com/en-us/library/vstudio/we2zys4d.aspx

默认行为是执行循环。在循环内, 函数首先尝试分配请求的存储空间

无论如何-我第二个什么n.m。发表评论

你需要修复真正的内存错误

这是不言自明的;出于任何调试目的 - 请查看 std::set_new_handler。

顺便说一句 - 我觉得你的代码有些地方很烦人

  • 运算符的明确限定
  • 不抛出 std::bad_alloc 而是在 catch-block 之外重新抛出

黑客愉快!

问候,S.

P.S.:@all:由于我在这里的经验有限,我不能“投票”这个问题,但我建议这样做。这是一个非常有趣的话题,而且表述得很好。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多