程序如何知道要释放多少内存?

时间:2011-09-27 23:11:14

标签: memory implementation

我怀疑我的问题的答案是特定于语言的,所以我想知道C和C ++。当我在缓冲区上调用free()或使用delete[]时,程序如何知道要释放多少内存?

缓冲区或存储的动态分配数组的大小在哪里?为什么程序员也无法使用它?

7 个答案:

答案 0 :(得分:2)

每个实现都会有所不同,但通常运行时分配的次数比请求的多一些,并使用块开头的一些隐藏字段来记住分配的大小。因此,返回给调用者的地址与从堆中声明的内存的起始位置相差一点。

调用者无法使用它,因为从堆中声明的真实内存量是一个实现细节,并且在编译器和平台之间会有所不同。至于知道调用者要求多少,而不是从堆中分配多少......好吧,语言设计者假设程序员能够在需要时记住这一点。

答案 1 :(得分:1)

为您提供该块内存的内存分配器负责所有维护数据。通常它存储在块的开头(就在您使用的实际地址之前),因此在释放时很容易访问。

关于您的其他问题:为什么您的应用应该知道它?这不是你的顾虑。它将内存分配管理与应用程序分离,因此您可以使用不同的分配器(出于性能或调试原因)。

答案 2 :(得分:1)

堆会跟踪所有已分配和可用的内存块,专门用于此目的。典型(如果是天真的)实现分配内存,在开始时使用几个字节进行簿记,并返回超过这些字节的地址。在后续操作(free / realloc)中,它将减去几个字节以进入簿记区域。

某些堆实现(例如,Windows“GlobalAlloc())让您知道给定起始地址的块大小。但是在C / C ++ RTL堆中,没有这样的服务。

请注意,malloc()有时会分配内存,因此有关malloc块大小的信息实用性有限。 C ++ new []'ed数组,这是另一回事 - 对于那些知道确切的数组大小对于阵列破坏正常工作至关重要。尽管如此,C ++中还没有dynamic_sizeof运算符这样的东西。

答案 3 :(得分:0)

它内部存储在依赖于语言/编译器/ OS的位置。

有时候它是可用的(例如C语言中的.Length),尽管这可能只涉及允许使用多少内存,而不是对象的总大小。

答案 4 :(得分:0)

通常因为free的大小存储在分配的缓冲区中。一种常见的技术是将大小存储在返回指针之前的内存中。

为什么程序员无法获得此类信息?我真的不知道。我想这是因为实现可能能够提供内存分配而无需实际存储其大小,并且这种实现 - 如果它存在 - 不应该受到其他人的惩罚。

答案 5 :(得分:0)

这不是语言特定的。这一切都由内存管理器完成。

它如何知道取决于内存管理器如何管理内存。一般的想法是内存管理器分配的内存比你要求的多。它存储有关这些位置中已分配内存块的额外数据。因此,当您释放内存时,它会使用存储在这些位置的信息(根据给定指针重建)并计算出要停止管理的实际内存量。

答案 6 :(得分:0)

不要混淆释放和破坏。

由于某些内部魔法(“实现定义”),

free()知道内存的 size ,例如分配器可以保存由相应指针索引的所有已分配内存区域的列表,只需查找指针以了解要释放的内容;或者该信息可以存储在一些隐藏数据块中的已分配内存本身旁边。

array-delete 表达式 delete[] arr;不仅释放内存,还调用所有析构函数。为此目的,仅知道内存大小是不够的,但我们还需要知道元素的数量。为此,new T[N]实际上分配更多而不是sizeof(T) * N字节的内存,因此数组删除器知道要调用多少个析构函数。所有内存都由相应的delete-operator正确释放。

相关问题