免费功能在C/Objective-C的工作不

问题描述:

可能重复:
How do malloc() and free() work?免费功能在C/Objective-C的工作不

我曾经遇到过一个奇怪的问题,我真的不知道为什么它不工作。

我有下面的代码在Xcode:

void *ptr = malloc(1024 * 1024 * 100); 
memset(ptr, 0, 1024 * 1024 * 100); 
free (ptr); //trace this line 
ptr = malloc (1024 * 1024 * 100); 
memset(ptr, 0, 1024 * 1024 * 100); 
free (ptr); //trace this line 

我把一个断点,在每一个*()线,当我跟踪的程序,*并没有真正释放了100MB。但是,如果我将数字从100更改为500(分配500mb两次),memset 500mb,free()可以正常工作。为什么?

+3

'免费()'总是“工作正常”。你应该做什么*期望*是什么错误。 –

+0

这是客观的C还是C? – djechlin

+0

你怎么能断言内存不是免费的? – Paolo

当您将一块内存传递给free时,该内存不一定会立即返回到操作系统。实际上,根据C标准的措辞,有人认为内存不能被退回到操作系统,直到程序退出。

问题的措辞是(C99,§720.3.2/ 2):“*函数导致ptr指向的空间被释放,也就是说,可用于进一步分配。他们的论点是,当/如果分配一块内存然后释放它时,它应该可以再次分配 - 但是如果它返回到操作系统,其他进程可能需要它,所以它不再可用于进一步分配,作为标准要求。我个人并不认为完全是说服力(我认为“另一个进程分配”仍然是分配),但这就是生活。

大多数库从OS分配大量内存,然后将这些大块的块分配给程序。当程序释放内存时,将该块内存放在“可用”列表*进一步分配。大多数(至少有时)遍历空闲块列表,合并相邻地址的空闲块。

许多人也遵循一些启发式规则,解释它在释放后应该保留的内存。首先,只要该块中的任何内存仍在使用中,就保留整个块。但是,如果块中的所有内存都已释放,它们会查看它的大小以及(通常)它们有多少可用内存。如果可用块的数量和/或空闲块的大小超过某个阈值,他们通常会将其释放回操作系统。

与其固定阈值不同,有些尝试通过(例如)基于可用存储器的百分比而不是固定大小来调整它们对环境的行为。没有这些,编写(比如说)十年前写入的程序在可用内存通常较小时通常会发生相当多的“颠簸” - 重复向OS分配和释放相同(或类似)大小的块。

free永远不会失败(它没有返回值),除非您用不正确的地址调用它,这会给您带来未定义的行为。

您不必烦恼free是否实际上释放了内存,或者您只需确保在完成动态内存使用后确保在正确的地址上调用free,否则编译器应该照顾好您。
这是你应该相信你的编译器能正确处理的东西之一。

此外,free只是标记内存释放释放(如名称说)以供重用。它不会将被释放的内存清零或初始化。

free()不必立即取消映射并返回操作系统之前备份但不再分配缓冲区的页面。它可以让它们保持在周围,这样你就可以快速地分配内存。程序结束后,页面将被取消映射并返回到操作系统。

正如其他人已经说过的,free()不必将内存返回到操作系统。但我拒绝了一个想法,即你不应该关心内存是否被返回。应该有很好的理由去关心,但有效的原因。

如果想要内存返回到操作系统,使用特定于平台的方式提供这样的保证:(有许多关于支持它的系统

  1. mmapMAP_ANONYMOUS,但MAP_ANONYMOUS不POSIX):mmap而不是malloc,munmap而不是free

  2. VirtualAllocVirtualFree在Windows上。

[Shoul我在这里添加其他系统的东西?随意建议。]

这些分配大内存单元(系统页面大小或更多)的内存工作方式。