new/malloc 似乎如何记住分配的数据量

How do new/malloc seem to remember amount of data allocated?

本文关键字:分配 数据 何记住 malloc new      更新时间:2023-10-16

为什么这不会导致内存泄漏?我在堆上分配了很长时间的空间,然后将指针更改回字符*。之后,我在此指针上调用 delete(或第二个示例中为 free)。这两个示例似乎都不会导致内存泄漏。

#include <stdlib.h>
struct leaky {
   long long* testptr;
   leaky() {testptr = new long long; }
   ~leaky() { void* newptr = (void*) testptr;
              char* newptr2 = (char*) newptr;
              delete newptr2; }
};
struct leaky2 {
   long long* testptr;
   leaky2() { testptr = (long long*) malloc(sizeof(long long)); }
   ~leaky2() { void* newptr = (void*) testptr;
               char* newptr2 = (char*) newptr;
               free (newptr2); }
};
int main() {
   while (true) {
      {
         leaky leak = leaky();
      }
   }
}

我对此进行了测试:GCC 版本 4.6.3 20120306 (Red Hat 4.6.3-2) (GCC)在 Unix 系统上。

第一段代码是未定义的行为,因为您无法从与new -ed 无关的类型中delete。第二种情况是正确的,所以我们可以讨论这种情况。

mallocfree的接口是基于void*的,所以类型在这里并不重要,但问题仍然存在:free怎么知道分配了多少malloc?答案是它是实现定义的。它可以通过不同的方式完成。分配器可以获取更大的内存块,并将信息存储在该额外空间中。在某些情况下,malloc从不同的池中为不同的固定大小(特别是对于小对象)分配信息,因此不需要使用可能很小的对象来跟踪信息。在这些情况下,free 的实现只需要弄清楚内存来自哪个池并将块返回到池中。

malloc

一些簿记信息与它返回给您的地址的值相关联(有时在地址之前的内存区域中)。 此簿记信息包含分配的大小。 转换地址不会更改此地址的值,只会更改代码对它的解释。

  1. 任何指向内存的指针都可以转换为char*并具有相同的值。 因此,强制转换为char*只会改变编译器解释值的方式(sizeof(*ptr)返回的内容等)。 它不会更改指针的值。

  2. operator deletefree()接受void*。 因此,当任何一方被要求释放内存时,任何"类型"的概念都已经消失了。 他们必须能够解释这一点,并在不知道这些字节过去是什么的情况下使用内存。

    作为参考,他们通常通过分配一点额外的内存并在地址返回给您之前以某些字节记录该内存的大小来做到这一点。 但这是一个实现细节;不要依赖它。

使用

malloc 或 new 时,使用的空间由"开销"(与已用内存块和可用内存块的大小有关的信息,指向所需空间的实际指针)和"有效负载"(正在使用的内存)组成。

用于此簿记信息的一种行话形式是"初始化记录",可能类似于以下结构

struct InitRecord
{
  int memBlockSize;
  void* mem;
};

这就是malloc记住你使用了多少mem的方式。进一步了解的一个好方法(也是一个有趣的练习!)是创建自己的堆分配器。

很好的参考资料在这里 http://www.cs.ucsb.edu/~rich/class/cs170/labs/lab1.malloc/index.html

和这里

http://systematicgaming.wordpress.com/2008/08/05/memory-management-introduction/