动态内存分配如何工作[重复]

Posted

技术标签:

【中文标题】动态内存分配如何工作[重复]【英文标题】:how does dynamic memory allocation work [duplicate] 【发布时间】:2013-12-20 05:52:02 【问题描述】:

在 C/C++ 中,当您想要动态分配内存时,通常调用 malloc void* malloc (size_t size);,它返回一个指向大小字节内存块的指针。 使用完此内存块后,您可以调用 free() 将内存释放回堆。

这很好,但是如果你碰巧调用 realloc void* realloc (void* ptr, size_t size); 会改变 ptr 指向的内存块的大小。使用完内存后仍然调用 free(),但我的问题是编译器如何知道要释放多少内存?

直觉上我可以想出一个答案,但我对实现细节很感兴趣——它是如何完成的?它依赖于编译器吗?它是标准的一部分吗?

提前致谢!

【问题讨论】:

在 C 中你会使用 malloc,但在 C++ 中你不会。 我已经看到它在 c/c++ 中使用过;天气好不好是另一回事 简短回答...这取决于。有许多 malloc/free 算法,其中一些针对各种使用模式进行了优化。此外,编译器不知道。这些例程由库实现。 另一个问题中没有出现的答案是,内存管理是动态的,不是在编译时确定的。 mallocfree(以及 realloccalloc 等)是具有自己的数据结构并动态跟踪内存分配的库函数。没有真正的标准(尽管有一些常用的算法),因为库可以根据需要选择实现内存管理。 【参考方案1】:

要释放内存,您通常不需要说明要释放多少 内存。分配器已经知道它给了你多少,并记住了这一点。分配内存的地址在分配器的内部簿记数据结构中充当一种“键”。所以你需要做的就是给出你想释放的内存的地址,分配器就知道你说的是哪块内存。

明确一点:没有所谓的“部分释放”一些内存。您不能指向一些已分配内存的中间并说“此处释放 100 个字节”。你准确地释放你获得的东西,不多也不少。

最后,realloc 只是mallocmemcpy 的组合,如果你愿意的话,也许还有一个小的优化机会,允许现有分配在不移动数据的情况下“增长”。但想法是一样的。

【讨论】:

我知道 malloc/realloc/free 是如何工作的,我很好奇编译器是如何记账的 编译器不做任何记账。这一切都在libc 中并动态跟踪。 操作系统负责记账。 《理解 linux 内核》这本书深入探讨了 linux 是如何做到这一点的(尽管它现在已经很老了)。 @Will:操作系统通常会进行更粗略的簿记。分配器库需要从操作系统中获取大块内存并自己处理细粒度的用户分配。 @Will:glibc malloc 使用mmap 进行大分配(高于可调阈值,如 64k),因此它绝对可以将它们交还给free 上的内核.如果程序暂时需要大量内存,但随后释放大部分内存并在之后长时间运行,这可以避免使用大量脏匿名页面。让它们被换出到磁盘会使最终重用它们(硬页面错误)更慢,而不是稍后必须再次向内核请求页面(通常是来自延迟分配的软页面错误)。

以上是关于动态内存分配如何工作[重复]的主要内容,如果未能解决你的问题,请参考以下文章

SIMD和动态内存分配[重复]

C ++如何在堆栈上动态分配内存?

Java如何分配和回收内存?Java垃圾收集器如何工作?

什么是 C++ 中的动态内存分配?

什么是 C++ 中的动态内存分配?

Linux 动态库如何节约内存