释放仅用"运算符new"分配的一部分内存。

时间:2015-03-05 18:12:16

标签: c++ memory memory-management memory-leaks

理论上,如果使用operator new分配内存空间,是否有可能以零散的方式释放内存?例如,如果void *mem = operator new(sizeof(int)*2)用于为两个int*变量分配内存地址,一个位于mem而另一个位于mem+sizeof(int),则可以释放内存一个,但不是另一个?

我的理解是operator new仅分配内存,并且不调用任何构造函数,因此使用placement new在内存中的精确空间调用构造函数。如果这些分配的内存地址是已知的,但在内存中不一定是线性的(例如,存储在内存池类的链表中),我会想象有一种合适的方法来释放分配的内存迭代内存地址的链接列表并释放分配大小的内存。但是,通过将内存分配给指向适当大小的数据类型的指针,始终会引发运行时错误。

有没有合适的方法呢?

理论范例:

// This works fine
uintptr_t mem1 = reinterpret_cast<uintptr_t>(operator new(sizeof(int)));
int *a = new(reinterpret_cast<void*>(mem1)) int(1);
printf("a|*a\t\t%p|%d\n", a, *a);
delete a;

// Both of the pointers can be assigned to the appropriate positions...
uintptr_t mem2 = reinterpret_cast<uintptr_t>(operator new(sizeof(int) * 2));
int *b = new(reinterpret_cast<void*>(mem2)) int(2);
printf("b|*b\t\t%p|%d\n", b, *b);
int *c = new(reinterpret_cast<void*>(mem2+sizeof(int))) int(3);
printf("c|*c\t\t%p|%d\n", c, *c);

// ...but attempting to delete them results in a runtime error.
operator delete(b);
operator delete(c);
//using "operator delete(reinterpret_cast<void*>(mem2));" works just fine, but I'm operating on the assumption that the addresses may be non-linear, in a linked-list of addresses of a constant size

2 个答案:

答案 0 :(得分:6)

18.6.1.1/12(void operator delete(void* ptr) noexcept):

  

要求:ptr应为空指针或其值应为先前调用(可能已替换)operator new(std::size_t)或operator new(std::size_t,const std::nothrow_t&)尚未失效的值返回的值通过对operator delete(void*)的干预电话。

我不认为你可以比分别破坏分配的内存更明确:标准不允许这样做。

答案 1 :(得分:0)

如果你的意思是“新操作员可以分配大量内存,然后将其中的一部分返回给调用者,使内存分配真正有效”,那么一般来说,是的......已经发生了什么。使用现代系统,您甚至不会分配任何内存 - 会发生的情况是,您只分配了一块虚拟地址空间,只有在您写入时才由实际内存支持,CPU MMU会为您处理所有这些。

不支持的是在应用程序代码级别分配内存并尝试部分释放它,你从new获得的是你必须用作单个块的内容。