当前位置: 首页 > 知识库问答 >
问题:

为什么malloc分配的内存空间比我要求的要多?[副本]

卫昊东
2023-03-14

我发现malloc()分配的内存空间比我要求的要多。

struct { void *ptr; int var; } msg;   // 16 bytes (checked by sizeof())

for (int i = 0; i < 100000000; i++)
    malloc(sizeof(msg));

正如前面提到的代码一样,malloc()实际上为每个函数调用分配了32个字节(由top计算),但valgrind实际上只显示了每个调用16个字节。

为什么malloc分配的内存空间比我要求的要多,以及如何强制malloc()不要浪费那么多内存空间?

令人惊讶的是,即使结构为24字节,它也分配32字节,所以我猜内存空间被浪费了。我不确定malloc()是否应该分配32字节的倍数。如果是真的,那么内存空间就被浪费了。

已编辑:

测试过其他情况。

+---------+---------------------------+
|    n    | memory usage of malloc(n) |
+---------+---------------------------+
|  1 ~ 24 |         32 bytes          |
+---------+---------------------------+
| 25 ~ 40 |         48 bytes          |
+---------+---------------------------+
| 41 ~ 56 |         64 bytes          |
+---------+---------------------------+

如果n不是16*m 8m ∈ ℕ. 当n等于22时,由于内存对齐而浪费的一些内存空间是可以理解的,但当n等于16时,它仍然应该被视为浪费。在大多数平台上,最小内存访问单元的大小为4字节或8字节,那么为什么GCC实现每次增加选择16字节。

共有3个答案

应涵容
2023-03-14

分配的多余字节(即开销)是特定于实现的,实现中的内存管理器分配内部跟踪/内部管理所需的内存。内存空间不会被视为浪费。您的担忧是真实的,尤其是当您看到数以百万计的小分配时——这将导致大量堆内存碎片,当然还有巨大的开销。因此,我可以想出两种选择——编写堆分配器或更好地使用由他人编写/测试/共享的内存管理器——从脸书的jemalloc或谷歌的tcmalloc开始-

颛孙飞
2023-03-14

由malloc()、calloc()等分配的任何额外内存(如果有的话)是系统的实现定义方面,不是由C指定的。

检查编译器的规范以确定原因。通常是为了内存管理。

要强制使用不同的分配方案,请重写malloc()或使用您自己的内存分配函数。

相野
2023-03-14

malloc()具有非常显着的运行时开销。GNU C库使用基于dlmalloc(“Doug Lea's Malloc”)的ptmalloc

堆上的内存分配为“块”,这是一个包含标头和可用内存的8字节对齐数据结构。分配的内存包含块大小和使用标志的816字节开销。未分配的块还存储指向可用空间区域中其他空闲块的指针,使最小块大小24字节

未分配的内存被分组到大小相似的“容器”中,通过使用区块的双链接列表实现(指针存储在区块内的未分配空间中)。

对于256字节以下的请求(“小箱”请求),使用简单的二次方最佳拟合分配器。如果该箱中没有可用块,则下一个最高箱中的块被一分为二。

你可以在这里了解更多

 类似资料:
  • C++20概念的一个特点是,在某些情况下,您必须编写。例如,[expr.prim.req]/3中的这个示例:

  • E/AndroidRuntime:致命异常:主进程:com.a3sumatch.multipart,PID:29240 java.lang.OutOfMemoryError:在Dalvik.System.VMRuntime.NewNonmovableArray(本机方法)在Android.Graphics.BitmapFactor.NativeDecodeAsset(本机方法)在Android.G

  • 我试图在Java做简单的聊天应用程序,但我得到这个错误。怎么了?我该怎么修好它?for循环中有一些错误? 我得到这个错误 线程“main”java.lang.IndexOutoFboundsException:索引0超出长度0的界限,位于java.base/jdk.internal.util.preconditions.OutoFbounds(preconditions.java:64)位于jav

  • 我多次运行这个程序,并对其中的每一个进行后台处理,直到不再有足够的内存可以分配。然而,这种情况从未发生过。我运行了一个linux命令,即使多次运行这个程序,空闲内存也从未减少过256 MB。 但是,另一方面,如果我使用而不是,那么就有一个巨大的区别:

  • 问题内容: 在大多数在线教程中,我们可以看到它们显示了GC中有两个幸存者空间。当我们实际上只有一个幸存者空间时,有什么需要?拥有两个幸存者空间会对性能产生什么影响? 问题答案: 原因是,您猜对了,性能。首先让我解释一下为什么还存在幸存者空间。关于 对象重定位 的基本考虑,有两种主要的垃圾收集器设计: 就地 压实 收集器; 一个 拷贝 收集器。 基本上,因为它永远不会覆盖任何对象,所以复制收集器可以

  • 我已经读了很多关于内存对齐的书,但我不明白,我知道这是一种重要的方法,要编写高效的代码,你必须牢记这一点。但我感到困惑。