大家好,
当我们定义free(指针)时,OS将如何知道我必须释放多少大小。 我的意思是我们没有提供任何大小,只指向免费声明。 如何内部处理大小?
谢谢, 尼尔
答案 0 :(得分:2)
操作系统不会有任何线索,因为免费不是系统调用。但是,当内存最初由malloc()分配时,C库内存分配系统将以某种方式记录大小,因此它知道要释放多少内容。
答案 1 :(得分:0)
大小存储在分配器内部,而传递给free的指针用于访问该数据。一个非常基本的方法是在指针之前存储4个字节的大小,所以从指针中减去4会给你一个指向它的大小的指针。
请注意,操作系统不直接处理它,它是由C / C ++运行时分配器实现的。
答案 2 :(得分:0)
当你调用malloc时,C库会自动在堆上为你留出空间。因为在堆上创建的东西是动态创建的,所以在任何给定时间点堆上的内容都不知道,因为它是堆栈的。因此,库将跟踪您在堆上分配的所有内存。
在某些时候,您的堆可能如下所示:
p---+
V
---------------------------------------
... | used (4) | used (10) | used (8) | ...
---------------------------------------
库将跟踪为每个块分配的内存量。在这种情况下,指针p指向中间块的开头。
如果我们进行以下调用:
free(p);
然后库会在堆上释放这个空间,就像这样......
p---+
V
----------------------------------------
... | used (4) | unused(10) | used (8) | ...
----------------------------------------
现在,下次你正在寻找一些空间,比如说:
void* ptr = malloc(10);
新未使用的空间可能会再次分配给您的程序,这将允许我们减少程序使用的总内存量。
ptr---+
V
----------------------------------------
... | used (4) | used(10) | used (8) | ...
----------------------------------------
您的图书馆在内部管理尺寸的方式可能不同。实现这一点的一种简单方法是在分配给每个块的大小的每个块的开头添加额外的字节数(我们在示例中说1)。所以我们之前的堆内存块看起来像这样:
bytes: 1 4 1 10 1 8
--------------------------------
... |4| used |10| used |8| used | ...
--------------------------------
^
+---ptr
现在,如果我们说块大小将被舍入为2可被整除,那么我们在大小的末尾有一个额外的位(因为我们总是可以假设它为0,我们可以方便地使用它们检查相应的块是使用还是未使用。
当我们在free中传递指针时:
free(ptr);
库会将指针移回一个字节,并将已使用/未使用的位更改为未使用。在这种特定情况下,我们甚至不必实际知道块的大小以释放它。当我们尝试重新分配相同数量的数据时,它只会成为一个问题。然后,malloc调用将在线下,检查下一个块是否空闲。如果它是空闲的,那么如果它是正确的大小,该块将返回给用户,否则将在堆的末尾剪切新块,并在必要时从操作系统分配更多空间。