我已经读过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
电话不会失败吗?
这对我的效率有什么帮助吗?我想的是,如果最初获得一个大块并且现在可以免费获得,那么内存管理会更好地进行内存管理。这会导致更少的碎片吗?
答案 0 :(得分:7)
最好保留分配的初始内存块,然后使用池将其提供给应用程序中的客户端。依靠深奥的行为来维护代码的稳定性并不是一种好的形式。如果任何更改,您可能会处理错误的指针并导致程序崩溃。
答案 1 :(得分:5)
您要求使用便携式和低级方式来控制内存接口的 OS端发生的事情。
在任何操作系统上(因为c是其中最广泛移植的语言之一)。
考虑一下,请记住操作系统的结构和目标各不相同,并且需求和属性有很多不同。
通常的c API只能定义界面的c外观和行为方式,而不是操作系统方面应该如何处理。
答案 2 :(得分:4)
不,你不能可靠地做这样的事情。它只是在可移植的意义上它是有效的C并且可能会在你尝试的任何地方编译,但依赖于这种假定的(和未记录的)行为仍然是不正确的。
您也不会获得任何明显更好的表现。对来自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。这是您获得可预测结果的唯一方法。其他依赖于模糊/无证的功能和作品的其他东西都归功于运气。