-2

可能重复:
malloc() 和 free() 如何工作?

我遇到了一个奇怪的问题,我真的不确定为什么它不起作用。

我在 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

我在每个 free() 行上都设置了一个断点,当我跟踪程序时,free 并没有真正释放 100mb。但是,如果我将数字从 100 更改为 500(分配 500mb 两次),memset 500mb, free() 工作正常。为什么?

4

4 回答 4

2

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

您不必担心是否free实际释放内存,您只需确保free在完成动态内存使用后调用正确的地址,编译器应该会照顾您。
这是您应该相信编译器能够正确处理的事情之一。

此外,free只需将被释放的内存标记为空闲(如名称所示)以供重用。它不会清零或初始化正在释放的内存。

于 2013-01-22T15:42:08.783 回答
0

当您将一块内存传递给 时free,该内存不一定会立即返回给操作系统。事实上,根据 C 标准中的措辞,有些人认为,在程序退出之前,内存不能归还给操作系统。

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

大多数库从操作系统分配大块内存,然后将这些大块的一部分子分配给程序。当程序释放内存时,将该内存块放在“可用”列表中以供进一步分配。大多数也(至少有时)遍历空闲块列表,合并相邻地址的空闲块。

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

有些人没有固定阈值,而是尝试通过(例如)将阈值基于可用内存的百分比而不是固定大小来调整其行为以适应环境。如果没有这些,十年前(比如说)在可用内存通常要小得多的情况下编写的程序通常会进行相当多的“颠簸”——反复向操作系统分配和释放相同(或相似)大小的块。

于 2013-01-22T18:18:28.540 回答
0

free()不必立即取消映射并将先前备份但不再分配缓冲区的页面返回给操作系统。它可能会保留它们,以便您可以再次快速分配内存。当程序完成时,页面将被取消映射并返回给操作系统。

于 2013-01-22T15:46:25.450 回答
0

正如其他人已经说过的那样,free()不必将内存返回给操作系统。但我拒绝你永远不应该关心内存是否被返回的想法。关心应该有充分的理由,但也正当的理由。

如果您确实想将内存返回给操作系统,请使用提供此保证的特定于平台的方式:

  1. mmapMAP_ANONYMOUS支持它的系统上(有很多,但MAP_ANONYMOUS不是 POSIX):mmap而不是mallocmunmap而不是free.

  2. VirtualAllocVirtualFree在 Windows 上。

[我应该在这里为其他系统添加一些东西吗?欢迎提出建议。]

这些分配内存的方式适用于大内存单元(系统页面大小或更大)。

于 2013-01-22T16:00:38.040 回答