在分配的内存上*不*使用free()是否可以?

Nic*_*ick 83 c c++ heap memory-leaks memory-management

我正在学习计算机工程,我有一些电子课程.我听到了,从我的两个教授(这些课程),有可能避免使用的free()功能(后malloc(),calloc()等),因为分配可能不会被再次使用的存储空间分配等内存.也就是说,例如,如果您分配4个字节然后释放它们,您将有4个字节的空间可能不会再次分配:您将有一个漏洞.

我认为这很疯狂:你不能拥有一个非玩具程序,你可以在堆上分配内存而不释放它.但是我没有足够的知识来解释为什么它如此重要以至于每一个都malloc()必须有一个free().

那么:在没有使用的情况下,是否有可能适合malloc()使用free()?如果没有,我该如何向我的教授解释这一点?

unw*_*ind 100

简单:只是阅读几乎任何半严重malloc()/free()实现的来源.通过这个,我的意思是处理调用工作的实际内存管理器.这可能位于运行时库,虚拟机或操作系统中.当然,代码在所有情况下都不是平等可访问的.

通过将相邻的孔连接到较大的孔中来确保存储器不会碎裂,这是非常常见的.更严重的分配器使用更严格的技术来确保这一点.

因此,我们假设您执行三次分配和取消分配,并按此顺序获取内存中的块:

+-+-+-+
|A|B|C|
+-+-+-+
Run Code Online (Sandbox Code Playgroud)

个别分配的大小无关紧要.然后你释放第一个和最后一个,A和C:

+-+-+-+
| |B| |
+-+-+-+
Run Code Online (Sandbox Code Playgroud)

当你最终释放B时,你(最初,至少在理论上)最终得到:

+-+-+-+
| | | |
+-+-+-+
Run Code Online (Sandbox Code Playgroud)

可以拆分成公正的

+-+-+-+
|     |
+-+-+-+
Run Code Online (Sandbox Code Playgroud)

即一个较大的自由块,没有碎片留下.

参考资料,如要求:

  • 我认为,值得一提的是虚拟地址空间不是物理内存的直接表示.物理内存中的碎片可由操作系统处理,而未由进程释放的虚拟内存也不会在物理上释放. (4认同)
  • 非常挑剔的评论:虽然这个概念得到了很好的解释,但实际的例子却被选中了......运气不好.对于任何查看dlmalloc的源代码并且感到困惑的人:低于特定大小的块总是2的幂并且相应地合并/拆分.所以我们最终(可能)有一个8字节块和1个4字节块,但没有12字节块.对于分配器而言,这是一种非常标准的方法,至少在台式机上,尽管嵌入式应用程序可能会更加小心其开销. (3认同)

Rei*_*ica 42

其他答案已经很好地解释了实际的实现malloc()并且free()确实将(defragmnent)孔合并到更大的空闲块中.但即使情况并非如此,放弃也是一个坏主意free().

问题是,你的程序只是分配(并希望释放)那4个字节的内存.如果它将运行一段延长的时间,它很可能需要再次分配4个字节的内存.因此,即使这4个字节永远不会合并到更大的连续空间中,它们仍然可以被程序本身重用.

  • 确切地说+1.问题是,如果"free"被调用足够多次以对性能产生影响,那么它可能也会被调用足够多次,以至于将其遗漏会对可用内存造成很大影响.很难想象一个嵌入式系统的情况,由于"free"而性能不断受到影响,但"malloc"只被称为有限次数; 有一个嵌入式设备进行一次性数据处理然后重置是一个相当罕见的用例. (6认同)

Pau*_*ans 10

这完全是胡说八道,例如有许多不同的实现malloc,有些尝试使堆更有效,如Doug Lea或者这个.


Lua*_*aan 9

您的教授是否有机会与POSIX合作?如果他们已经习惯了写大量的小,简约的外壳应用程序,这是一个场景,我能想象这种做法也不会太糟糕-在OS的休闲释放整个堆一次是比释放快千变量.如果您希望您的应用程序运行一两秒钟,您可以很容易地完全没有取消分配.

当然,这仍然是一个不好的做法(性能改进应该总是基于剖析,而不是模糊的直觉),并且在没有解释其他限制的情况下,这不是你应该对学生说的,但我可以想象很多小管壳 - 应用程序以这种方式编写(如果不是直接使用静态分配).如果你正在开发一些不会释放变量的东西,那么你要么在极低延迟条件下工作(在这种情况下,你怎么能负担得起动态分配和C++?:D),或者你是做一些非常非常错误的事情(比如通过一个接一个地分配一千个整数来分配一个整数数组而不是一个单独的内存块).


Pad*_*118 5

你提到他们是电子学教授.它们可能用于编写固件/实时软件,能够准确地计算时间,通常需要执行.在那些知道你有足够的内存用于所有分配并且不释放和重新分配内存的情况下,可以给出更容易计算的执行时间限制.

在某些方案中,硬件存储器保护也可用于确保例程在其分配的存储器中完成或在非常特殊的情况下生成陷阱.

  • 那是个很好的观点.但是,我希望在这种情况下他们不会使用`malloc`等,而是依赖静态分配(或者可能分配一个大块,然后手动处理内存). (10认同)