有什么理由重载全局新建和删除?

除非您正在编程操作系统或嵌入式系统的某些部分,否则有任何理由这样做? 我可以想象,对于一些经常被创建和销毁的特定类而言,重载内存管理函数或者引入一个对象池可能会降低开销,但是在全局上做这些事情呢?

加成
我刚刚发现一个重载删除函数的错误 - 内存并不总是被释放。 这是一个不太重要的内存关键应用程序。 而且,禁用这些过载只会使性能下降约0.5%。


我们因为多种原因而在全球范围内重载新的和删除操作符:

  • 汇集所有小分配 - 减少开销,减少碎片,可以提高小型应用程序的性能
  • 制定分配与已知的生命周期-忽略所有的FreeS直到这一时期的最末端,然后自由所有的人都在一起(当然我们这样做更多具有本地运算符重载不是全局)
  • 对齐调整 - 缓存线边界等
  • alloc fill - 帮助公开使用未初始化的变量
  • 免费填充 - 帮助公开以前删除的内存的使用
  • 免费延迟 - 提高免费填充的有效性,偶尔会提高性能
  • 哨兵fenceposts - 帮助揭露缓冲区溢出,underruns和偶尔的野生指针
  • 重定向分配 - 考虑NUMA,特殊内存区域,甚至将单独的系统分开存储在内存中(例如嵌入式脚本语言或DSL)
  • 垃圾收集或清理 - 对于那些嵌入式脚本语言来说也很有用
  • 堆验证 - 您可以遍历堆数据结构每N次分配/释放以确保一切正常
  • 会计 ,包括泄漏跟踪使用快照/统计 (堆栈,分配年龄等)
  • 新/删除会计的想法非常灵活和强大:例如,您可以在发生分配时记录活动线程的整个callstack,并汇总关于该分析的统计信息。 如果您因为任何原因没有足够的空间保存本地堆栈信息,则可以通过网络发送堆栈信息。 您可以在这里收集的信息类型仅受限于您的想象力(当然还有性能)。

    我们使用全局重载,因为在那里挂载大量常用调试功能非常方便,并且可以根据我们从相同过载收集的统计信息对整个应用程序进行全面改进。

    我们仍然使用各种类型的自定义分配器; 在许多情况下,通过为例如单个STL数据结构的使用点提供自定义分配器,您可以获得的加速或性能远远超过您可以从全局过载获得的通用加速。

    看看C / C ++的一些分配器和调试系统,你会很快提出这些和其他的想法:

  • 的valgrind
  • 电围栏
  • dmalloc
  • dlmalloc
  • 应用程序验证器
  • 保证++
  • 的BoundsChecker
  • ......还有很多其他......(gamedev行业是一个很好的看点)
  • (一本古老但有创意的书是写固体代码,它讨论了许多您可能想要在C中提供自定义分配器的原因,其中大部分仍然非常相关。)

    显然,如果你可以使用这些优秀的工具,你会想要这样做,而不是自己动手。

    有些情况下,它更快,更容易,更少的商业/法律麻烦,没有什么可用于您的平台,或只是更具启发性:挖掘并编写全球超载。


    重载new和delete的最常见原因仅仅是检查内存泄漏和内存使用情况统计信息。 请注意,“内存泄漏”通常会导致内存错误。 您可以检查诸如双重删除和缓冲区溢出等情况。

    之后的用途通常是内存分配方案,如垃圾收集和池化。

    所有其他情况只是具体的事情,在其他答案中提到(记录到磁盘,内核使用)。


    除了这里提到的其他重要用途(如内存标记)之外,它也是强制应用程序中的所有分配通过固定块分配的唯一方式,这对性能和分段有着巨大的影响。

    例如,您可能有一系列固定块大小的内存池。 覆盖全局new可让您将所有61字节的分配引导至具有64字节块的池,全部768-1024字节分配给1024b块池,所有高于2048字节块池的分配以及任何其他任何内容大于8kb到一般粗糙的堆。

    因为固定块分配器比分配堆栈更加快速并且不容易碎片化,这使您可以强制甚至蹩脚的三方代码从池中分配,而不是遍布整个地址空间。

    这经常在对时间和空间至关重要的系统中完成,例如游戏。 280Z28,Meeh和Dan Olson描述了为什么。

    链接地址: http://www.djcxy.com/p/73027.html

    上一篇: Any reason to overload global new and delete?

    下一篇: wait status, how to fix it?