为啥 C 中没有“memsize”,它返回使用 malloc 在堆中分配的内存块的大小?

Posted

技术标签:

【中文标题】为啥 C 中没有“memsize”,它返回使用 malloc 在堆中分配的内存块的大小?【英文标题】:Why isn't there a "memsize" in C which returns the size of a memory block allocated in the heap using malloc?为什么 C 中没有“memsize”,它返回使用 malloc 在堆中分配的内存块的大小? 【发布时间】:2011-06-25 00:01:32 【问题描述】:

好的。在 Visual Studio 中,它可以被称为 _msize 中的任何其他名称。

但是为什么在给定使用 malloc 分配的内存块的情况下返回内存大小不是标准?由于我们无法判断 malloc 后面的返回指针指向了多少内存,因此我们可以在需要时使用这个“memsize”调用来返回该信息。 “memsize”和 malloc/free 一样是特定于实现的

只是询问,因为有时我不得不写一个 wrapper 来存储一些额外的字节大小。

【问题讨论】:

既然你,程序员,最初是负责分配内存的,你应该已经知道块的大小了。 @Maxim Yegorushkin 唯一的情况是我必须编写包装器使用第三方库,该库需要一些内存分配/释放,并保持全局分配多少内存的计数。因此,在释放时,我需要知道为即将释放的块分配了多少内存。这是图书馆工作所必需的。 @Paul R 这是正确的,因此我提到了包装器。我只是好奇,所以这个问题 @MeThinks:但是free() 已经为您管理好了! @Steve 我曾在 C 标准委员会 X3J11 任职。通常只有在需要的人有足够的影响力时才会添加东西——主要是编译器供应商。 【参考方案1】:

因为 C 库(包括 malloc)是为最小开销而设计的。像您想要的那样的函数需要实现来记录分配的确切大小,而实现现在可以根据需要选择“四舍五入”大小,以防止在realloc 中实际重新分配。

存储大小需要每次分配额外的size_t,这对于嵌入式系统可能很重。 (对于在编写 C89 时仍然很丰富的 PDP-11 和 286。)

【讨论】:

是的。当然,标准可以简单地说_msize的返回值只保证至少和分配的内存块一样大…… 这毫无意义。大小已记录(否则free() 将不起作用)。我认为真正的答案是没有人真正看到它有任何用处。 OP 的情况相当独特,并且比 C 库中的缺陷更能说明库设计不佳。 更有用的是,标准可以定义这个假设的“memsize”允许返回大于请求的大小,但如果这样做,那么额外的内存可以由程序寻址。这以一种可能有用的方式涵盖了常见情况(四舍五入到便于分配器的实现细节的大小)。一些程序可以从额外的内存中受益,例如,如果它是 I/O 缓冲区、循环消息队列、子分配器或扩展数组(如 C++ 中的 std::vector)。 @larsmans:当然,但这也更难,因为足够的 C++ reallocate 必须根据类型正确复制。请注意vector 不像new[] 那样分配初始化对象的数组,它使用分配器接口来获取原始数据并自行初始化,因此这样的reallocate 也必须只复制调用者的对象告诉它已初始化。将许多繁琐的细节推入调用堆栈。 realloc 只处理 POD,所以不需要。 std::vector 最受益的是使用移动语义重新分配,我想,C++0x 是做什么的? TMN 和 Steve Jessop 是正确的。这是一个糟糕的答案,因为没有必要——或希望——记录通过 malloc 请求的确切大小; memsize 应该返回可用的实际数量,这必须是已知的;如果不是内存被释放后无法重新分配。【参考方案2】:

要扭转这种局面,为什么要有?标准中已经有很多东西,尤其是 C++ 标准。您的用例是什么?

你请求一个足够大的内存块,你得到了它(或者一个空指针或异常)。可能会分配也可能不会分配额外的字节,其中一些可能会被保留。这在概念上很简单:你要求你想要什么,你就会得到一些你可以使用的东西。

为什么要复杂化?

【讨论】:

没有试图复杂化。只是好奇,因为我有一个需要它的用例。我在 *** 上看到了很多关于这个非常需要知道大小的问题。这绝不会贬低您非常有效的批评 @MeThinks:当然,只是想指出向标准添加功能不是免费的。 FWIW,我不记得在这方面看到过明显数量的问题。 轻微变体的用例包括 I/O 缓冲区、循环消息队列、子分配器或扩展数组(如 C++ 中的 std::vector)。所有这些都可以有效地使用分配器浪费的任何额外内存,只要他们知道有多少。除此之外:Windows、linux 和 OSX 都有专有的扩展来做到这一点,这表明有很好的理由让它复杂化。我想知道,是否有任何 C 实现/分配器不能轻易支持它?如果是这样,那么这就是不使其复杂化的原因,这可能胜过添加它的充分理由。 至于明显数量的问题,***.com/questions/1208644/…、***.com/questions/232691/…、***.com/questions/197839/… @Steve 在某个地方,free 必须知道内存块有多大,否则永远无法再从它分配。我已经编写了几个 malloc 并阅读了许多其他人的内容,我可以向您保证,没有任何实现不能轻易支持它。但是将它添加到标准中为时已晚,因为这会使任何使用它的代码与所有现有实现不兼容。【参考方案3】:

我认为没有明确的答案。该标准的开发人员可能考虑过它,并权衡了利弊。任何进入标准的东西都必须由每个实现来实现,因此向其中添加东西会给开发人员带来很大的负担。我猜他们只是没有发现该功能有用到足以证明这一点。

【讨论】:

【参考方案4】:

在C++中,你所说的包装器由标准提供的。如果用std::vector分配一块内存,可以使用成员函数vector::size()来确定数组的大小,使用vector::capacity() 来确定分配的大小(可能不同)。

另一方面,C 是一种低级语言,将这些问题留给开发人员管理,因为动态跟踪它(如您所建议的那样)并不是绝对必要的,并且在许多情况下是多余的。

【讨论】:

我包含了一个 C++ 答案,因为该问题最初包含 C++ 并使用了 C++ 标签。此外,C++ 答案为我对 OP 的实际问题的回答提供了上下文:“为什么在 C/C++ 中没有与 malloc() 一起使用的 memsize()”。

以上是关于为啥 C 中没有“memsize”,它返回使用 malloc 在堆中分配的内存块的大小?的主要内容,如果未能解决你的问题,请参考以下文章

为啥我在c编程中不能成功使用return选项?

用vs2019编写c语言程序,明显语法错误为啥不回报错,没有加return 0;

为啥 lambda 函数默认会丢弃推导的返回类型引用?

为啥当我让这个函数返回它的值时,函数会无限重复自己?

c中的return语句???为啥这个函数总是返回 20?

为啥没有返回语句时没有编译器错误?