总是(便携)释放和释放为进程保留内存或返回操作系统

时间:2010-06-21 18:39:25

标签: c malloc

我已经读过free()“一般”不会将内存返回给操作系统。我们可以移植使用free()的功能吗?例如,这是便携式吗?

 /* Assume I know i would need memory equivalent to 10000 integers at max
    during the lifetime of the process */

 unsigned int* p = malloc(sizeof(unsigned int) * 10000);

 if ( p == NULL)
  return 1;

 free(p);

 /* Different points in the program */

 unsigned int* q = malloc(sizeof(unsigned int) * 5);

 /* No need to check for the return value of malloc */

我正在编写一个演示,我事先知道要支持多少call contexts

是否可以提前分配"n""call contexts" structures,然后立即free。这样可以保证我未来的malloc电话不会失败吗?

这对我的效率有什么帮助吗?我想的是,如果最初获得一个大块并且现在可以免费获得,那么内存管理会更好地进行内存管理。这会导致更少的碎片吗?

10 个答案:

答案 0 :(得分:7)

最好保留分配的初始内存块,然后使用池将其提供给应用程序中的客户端。依靠深奥的行为来维护代码的稳定性并不是一种好的形式。如果任何更改,您可能会处理错误的指针并导致程序崩溃。

答案 1 :(得分:5)

您要求使用便携式和低级方式来控制内存接口的 OS端发生的事情

任何操作系统上(因为c是其中最广泛移植的语言之一)。

考虑一下,请记住操作系统的结构和目标各不相同,并且需求和属性有很多不同。

通常的c API只能定义界面的c外观和行为方式,而不是操作系统方面应该如何处理。

答案 2 :(得分:4)

  1. 不,你不能可靠地做这样的事情。它只是在可移植的意义上它是有效的C并且可能会在你尝试的任何地方编译,但依赖于这种假定的(和未记录的)行为仍然是不正确的。

  2. 您也不会获得任何明显更好的表现。对来自NULL的{​​{1}}返回进行简单检查并不会导致您的程序变慢。如果您认为拨打malloc()malloc() 的所有电话会降低您的程序速度,请使用您想要的行为编写您自己的分配系统。

答案 3 :(得分:4)

您无法移植依赖malloc()的任何此类行为。您只能依靠malloc()为您提供指向给定大小的块内存的指针,您可以在调用free()之前使用该内存。

答案 4 :(得分:4)

嗯,不。 malloc(3)内部的作用是调用brk(2)来扩展数据段,如果它对于给定的分配请求来说太小了。它确实触及了一些内部簿记页面,但通常并不是所有分配的页面都可能在那时由物理内存支持。

这是因为许多操作系统内存过度使用 - 承诺应用程序无论其请求的是什么,无论可用的物理内存如何,希望应用程序不会使用所有内存,其他应用程序释放内存/终止,并作为最后的手段回到交换。在Linux malloc(3)上说几乎不会失败。

当内存实际被引用时,内核必须找到可用的物理页面进行备份,创建/更新页表和TLB等 - 正常处理页面错误。所以,不,你不会在以后获得任何加速,除非你去触摸那个分配的块中的每一页。

Disclamer:上面的内容对于Windows来说可能不准确(所以,再也没有了 - 没有任何便携性。)

答案 5 :(得分:3)

不,没有保证free()不会释放内存,并且无法保证你的第二个malloc会成功。

即使是“通常”不向操作系统返回内存的平台,如果可以,也会这样做。你可能最终得到你的第一个malloc成功,而你的下一个malloc没有成功,因为同时系统的其他部分耗尽了你的记忆。

答案 6 :(得分:3)

完全没有。它根本不便携。此外,无法保证另一个进程不会使用有问题的内存 - C在许多设备上运行,例如嵌入式虚拟内存寻址不存在的设备。它也不会减少碎片 - 你必须知道机器的页面大小并分配一定数量的页面 - 然后,当你释放它们时,它们只会再被碎片化。

如果你真的想要保证malloced内存,malloc一个大块并手动将对象放入其中。这是唯一的方法。至于效率,你必须在一个令人难以置信的饥饿设备上运行,以节省一些ifs。

答案 7 :(得分:3)

malloc(3)也执行mmap(2),因此,free(3)执行munmap(2),因此,第二个malloc()理论上可能失败。

答案 8 :(得分:1)

C标准可以理解为需要这样,但从实际的角度来看,已知的实现不遵循这一点,因此无论是否需要,您都不能真正依赖它。

所以,如果你想保证这一点,你几乎需要编写自己的分配器。一个典型的策略是从malloc(或其他)中分配一个大块,并为程序的其余部分分配部分,以便在该大块(或许可能是大块)中使用。

答案 9 :(得分:0)

为了更好地控制,您应该创建自己的内存分配器。内存分配器的一个例子是this one。这是您获得可预测结果的唯一方法。其他依赖于模糊/无证的功能和作品的其他东西都归功于运气。