所以我在堆中分配了256个块:
char* ptr1 = malloc(128);
char* ptr2 = malloc(128);
现在,在我释放ptr2之后,我认为它当前位于堆顶部,程序中断(堆的当前位置)不会减少。但是,如果我执行另一个malloc,则malloc返回的地址与释放的地址相同。
所以我有以下问题:
当我释放一个块时,为什么程序没有减少? 当我自由地调用究竟发生了什么?它如何跟踪释放的内存,以便下次我声明malloc时地址是相同的?
答案 0 :(得分:4)
这是未指明的行为。除非您只关心一个特定的平台/ os / compiler / libc组合,否则您不能依赖任何单一答案。您没有指定操作系统,C标准没有描述或要求任何特定的实现。从C99(我还没有最终发布的C11版本):
7.20.3
连续调用分配的存储顺序和连续性 calloc,malloc和realloc函数未指定。指针 如果分配成功,则返回适当的对齐,以便它可以 被分配给指向任何类型对象的指针,然后用于访问 分配的空间中的此类对象或此类对象的数组 (直到空间被明确解除分配)。一生的一生 分配的对象从分配扩展到解除分配。 每个这样的分配都应该产生一个指向不相交的对象的指针 任何其他物体。返回的指针指向开头(最低点 字节地址)分配的空间。如果空间不能 分配后,返回空指针。如果空间的大小 请求为零,行为是实现定义的:a 返回null指针,或者行为就像大小一样 非零值,但不应使用返回的指针 访问一个对象。
答案 1 :(得分:2)
这个manual的GNU libc可能会有所帮助。
这是要点
有时,free实际上可以将内存返回给操作系统 并使过程更小。通常,它所能做的只是稍后允许 调用malloc来重用空间。与此同时,空间仍然存在 在您的程序中作为malloc内部使用的自由列表的一部分。
答案 2 :(得分:0)
当我释放一个块时,为什么程序不会中断?
我相信它不会减少,因为已经为该程序提供了内存。
当我致电
free()
时究竟发生了什么?
该部分内存被标记为可分配,其先前的内容可以被覆盖。
考虑这个例子......
[allocatedStatus][sideOfAllocation][allocatedMemory]
^-- Returned pointer
考虑到这一点,free()
可以将[allocatedStatus]
标记为false,因此堆上的未来分配可以使用该内存。
如何跟踪
free()
d内存,以便下次我声明malloc()
地址是一样的吗?
我不认为这样。它只是扫描了一些空闲内存,发现之前被标记为空闲的块。
答案 3 :(得分:0)
我相信这完全取决于操作系统一旦你调用free(),它可能会选择立即回收那个内存或者不关心,只是将该内存段标记为可能的后续时间(可能是同样的事情) 。据我所知,在Windows上的free()之后,内存(如果很重要)显示在任务管理器中可用。
请记住,我们在这里讨论的内存是虚拟。这意味着操作系统可以告诉您它想要的任何内容,并且可能无法准确表示机器的物理状态。
想想如果你在编写操作系统时如何管理内存分配,你可能不想做任何可能浪费资源的事情。我们在这里讨论128个字节,您是否希望浪费宝贵的处理时间来单独处理它?这可能是这种行为与否的原因,至少是合理的。 在循环中执行,然后在另一个循环中执行free()或者只分配大块内存,看看会发生什么,实验。
答案 4 :(得分:0)
以下是内存分配器的工作原理:
你有一个分配器,它有一堆“bins”(“空闲列表”),它们只是空闲内存块的链接列表。每个bin都有一个与之关联的不同块大小(即:你可以有一个8字节块,16字节块,32字节块等的列表......甚至任意大小,如7或10字节块)。当程序请求内存时(通常通过malloc()),分配器将转到适合您数据的最小bin,并检查其中是否有任何空闲内存块。如果没有那么它将从操作系统(通常称为页面)请求一些内存并切断它返回到一堆较小的块以填充bin的块。然后它会将这些空闲块之一返回给您的程序。
当你自由呼叫时,分配器获取该内存地址并将其放回到它所来自的bin(也就是空闲列表)中,并且每个人都很高兴。 :)
内存仍在使用,因此您不必保留分页内存,但对于您的程序,它是免费的。