【问题标题】:How do new/malloc seem to remember amount of data allocated?new/malloc 似乎如何记住分配的数据量?
【发布时间】:2013-10-21 17:18:30
【问题描述】:

为什么这不会导致内存泄漏?我在堆上分配了 long long 的空间,然后将返回的指针更改为 char*。之后,我在这个指针上调用 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 系统上。

【问题讨论】:

  • 注意 malloc 返回 (void*) 所以如果它在类型上进行中继,它会在 malloc 返回后丢失。诸如 malloc 之类的分配器会保留一个标头(有时也是一个尾随数据),以便它们确定分配的大小。

标签: c++ c


【解决方案1】:

第一段代码是未定义的行为,因为您不能使用与您 new-ed 无关的类型来使用 delete。第二种情况是正确的,所以我们可以讨论一下。

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

【讨论】:

    【解决方案2】:

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

    【讨论】:

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

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

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

      【讨论】:

      • 一个值得注意的例外是伙伴系统分配器,其中分配的大小由指针值暗示。
      • 另一个值得注意的例外是@dribeas 提到的池分配器
      【解决方案4】:

      当使用 malloc 或 new 时,使用的空间包括“开销”(与已用和空闲内存块的大小有关的信息,指向您需要的空间的实际指针)和“有效负载”(正在使用的内存) .

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

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

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

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

      这里

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-05-16
        • 2020-02-03
        • 2010-12-16
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多