1
76
我们重载全局的new和delete操作符,我在其中工作的原因有很多:
新的/删除记帐的思想是非常灵活和强大的:例如,您可以在每次发生alloc时记录活动线程的整个调用堆栈,并汇总有关它的统计信息。如果由于任何原因,您没有空间在本地保存堆栈信息,那么可以通过网络发送它。你可以在这里收集到的信息类型只受你的想象力(当然还有性能)的限制。 我们使用全局重载是因为在那里挂起许多常见的调试功能很方便,并且根据我们从相同的重载中收集的统计数据,在整个应用程序中进行全面的改进。 我们仍然为单个类型使用自定义分配器;在许多情况下,通过提供自定义分配器(例如,STL数据结构的单点使用)可以获得的加速或功能远远超过了全局重载可以获得的一般加速。 看一下C/C++中的一些分配器和调试系统,你会很快想出这些和其他的想法:
(一本古老但具有开创性的书是 Writing Solid Code ,它讨论了您可能希望在C中提供自定义分配器的许多原因,其中大部分仍然非常相关。) 显然,如果你能使用这些好的工具中的任何一个,你将希望这样做,而不是滚动你自己的。 在某些情况下,它更快、更容易、更少的业务/法律麻烦、您的平台还没有可用的东西,或者只是更具启发性:挖掘并编写一个全球性的过载。 |
2
26
重载new和delete的最常见原因是检查 memory leaks 和内存使用统计。注意,“内存泄漏”通常被概括为内存错误。您可以检查诸如双重删除和缓冲区溢出之类的内容。 之后的用途通常是内存分配方案,例如 garbage collection 和 pooling . 所有其他情况都只是一些特定的事情,在其他答案(登录到磁盘,内核使用)中提到。 |
3
15
除了这里提到的其他重要用途(如内存标记)外,它也是强制应用程序中的所有分配进行固定块分配的唯一方法,这对性能和碎片化有着巨大的影响。
例如,您可能有一系列具有固定块大小的内存池。覆盖全局
由于固定块分配器比随意从堆中分配快得多,而且不太容易碎片化,这使得您可以强制甚至很糟糕的3D参与方代码从池中分配,而不是在整个地址空间中进行poop。 这通常是在时间和空间至关重要的系统中完成的,例如游戏。280Z28、Meeh和Dan Olson描述了原因。 |
4
10
Unrealengine3作为其核心内存管理系统的一部分,重载全局new和delete。有多个分配器提供不同的特性(分析、性能等),它们需要所有的分配来完成它。 编辑:对于我自己的代码,我只会把它作为最后的手段。我的意思是,我几乎肯定不会使用它。但我的个人项目显然要小得多/要求非常不同。 |
5
6
一些实时系统会过载,以避免在初始化后使用它们。 |
6
4
重载新建和删除使您可以向内存分配中添加标记。我标记每个系统或控件或中间件的分配。我可以在运行时查看每种方法的使用量。也许我想看看从UI中分离出来的解析器的用法,或者中间件的实际使用量有多大! 您还可以使用它在分配的内存周围放置保护带。如果/当你的应用程序崩溃时,你可以看看地址。如果您将内容视为“0xabcdao”(或任何您选择作为保护的内容),则表示您正在访问不属于自己的内存。 也许在调用了delete之后,您可以用类似的可识别模式填充这个空间。 我相信VisualStudio在调试中做了类似的事情。它不是用0xCDCDCDCD填充未初始化的内存吗? 最后,如果您有碎片问题,可以使用它重定向到块分配器?我不确定这到底是多久一次的问题。 |
7
3
当调用new和delete在您的环境中不起作用时,您需要重载它们。 例如,在内核编程中,默认的new和delete不起作用,因为它们依赖用户模式库来分配内存。 |
8
2
从实际的角度来看,最好在系统库级别覆盖malloc,因为operator new可能无论如何都会调用它。 在Linux上,您可以将自己的malloc版本替换为System One,如下面的示例所示: http://developers.sun.com/solaris/articles/lib_interposers.html 在那篇文章中,他们试图收集性能统计数据。但是如果您也覆盖了free,那么您也可能检测到内存泄漏。 因为您是在一个带有ld_预加载的共享库中执行此操作,所以您甚至不需要重新编译应用程序。 |
9
2
我在一个“安全”系统中看到过
正如您可能想象的那样,这有许多问题,但它确实起到了作用(大部分),并且避免了团队在一个相当大的现有应用程序中审查每个内存分配。 当然不是说这是一个很好的用途,但它可能是其中一个更有想象力的…
|
10
2
用C++编写的PS图象处理软件插件应该重写
|
11
2
我用内存映射文件来完成这项工作,这样写入内存的数据也会自动保存到磁盘上。
但99%的时间是作为调试功能完成的,用来记录分配和释放内存的频率、位置和时间。 |
12
2
实际上,对于游戏来说,从系统中分配一大块内存,然后通过重载new和delete提供定制的分配器是很常见的。一个很大的原因是控制台的内存大小是固定的,这使得泄漏和碎片化都有很大的问题。 通常(至少在封闭平台上)默认堆操作缺少控制和自省。对于许多应用程序来说,这并不重要,但是对于在固定内存情况下稳定运行的游戏来说,增加控制和内省都是非常重要的。 |
13
2
对于您的应用程序来说,除了随机崩溃之外,它还能够响应内存不足的情况,这是一个很好的技巧。做这个你的
最简单的技术是在启动时为这个目的保留一个空白内存块。你也可能有一些缓存你可以利用-想法是一样的。 当第一次分配失败开始时,您仍然有时间警告用户内存不足的情况(“我可以再活一段时间,但您可能希望保存您的工作并关闭一些其他应用程序”),将状态保存到磁盘,切换到生存模式,或者在您的上下文中任何其他有意义的情况。 |
14
0
最常见的用例可能是泄漏检查。 另一个用例是,当您的环境中有特定的内存分配需求,而您使用的标准库不满足这些需求时,例如,您需要确保在多线程环境中内存分配是无锁的。 |
15
0
正如许多人所说,这通常在性能关键型应用程序中完成,或者能够控制内存对齐或跟踪内存。游戏经常使用自定义内存管理器,尤其是针对特定平台/控制台时。 这是一个相当不错的 blog post about one way of doing this 还有一些推理。 |
rookie · 检查函数模板的所有参数包参数是否属于int 1 年前 |
ivaigult · -W转换和隐式字符串到布尔类型转换 1 年前 |
rainer · 后台插入程序的初始化 1 年前 |
Community wiki · 以理智、安全和高效的方式复制文件 1 年前 |
Shefali Kanaujia · 对C中向量的向量进行排序++ 1 年前 |
Ma Joonyoung · 粗粒度和细粒度链表的时间比较 1 年前 |