[英]How do new/malloc seem to remember amount of data allocated?
为什么这不会导致内存泄漏? 我在堆上长时间分配空间,然后更改指针,我回到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();
}
}
}
我测试了这个:Unix系统上的gcc版本4.6.3 20120306(Red Hat 4.6.3-2)(GCC)。
第一段代码是未定义的行为,因为您无法从与您new
内容无关的类型中delete
。 第二种情况是正确的,所以我们可以讨论那个。
malloc
和free
的接口基于void*
,所以类型在这里并不重要,但问题仍然存在: free
如何知道malloc
分配了多少? 答案是它是实现定义的。 它可以以不同的方式完成。 分配器可以获取更大的内存块并将信息存储在该额外空间中。 在某些情况下, malloc
从不同的池中为不同的固定大小(特别是小对象)分配,因此不需要使用可能很小的对象来跟踪信息。 在这些情况下, free
的实现只需要确定内存来自哪个池并将块返回池中。
malloc
一些簿记信息与它返回给你的地址的值相关联(有时在地址之前的内存区域)。 该簿记信息包含分配的大小。 周围的转换地址不会改变此地址的值,只会改变您的代码对它的解释。
任何指向内存的指针都可以转换为char*
并返回并具有相同的值。 因此,转换为char*
只会改变编译器解释值的方式( sizeof(*ptr)
返回等)。 它不会更改指针的值。
operator delete
和free()
接受void*
。 因此,当被要求释放内存时,无论如何,任何“类型”的概念都会消失。 他们必须能够解释这一点并使用内存,而不知道那些字节曾经是什么。
作为参考,它们通常通过分配一些额外的内存并在返回给您的地址之前的某些字节中记录该内存的大小来实现。 但这是一个实施细节; 不要依赖它。
当使用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/
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.