Theoretically, if space in memory was allocated using operator new
, would it be possible to free that memory in a piecemeal fashion? For instance, if void *mem = operator new(sizeof(int)*2)
was used to assign a memory address to two int*
variables, one at mem
and the other at mem+sizeof(int)
, is it possible to free the memory of one, but not the other?
从理论上讲,如果使用operator new分配内存空间,是否可以以零散的方式释放内存?例如,如果void * mem = operator new(sizeof(int)* 2)用于将内存地址分配给两个int *变量,一个在mem,另一个在mem + sizeof(int),是否可以释放一个人的记忆,而不是另一个人的记忆?
It's my understanding that operator new
only allocates memory, and doesn't call any constructors, so placement new
is used to call the constructor at an exact space in memory. If the memory addresses of these allocations are known, but aren't necessarily linear in memory (stored in a linked list in a memory pool class, for example), I would imagine that there would be an appropriate way to free the allocated memory by iterating through the linked list of memory addresses and freeing the memory of the size of the allocation. However, by assigning the memory to a pointer to a data type of the appropriate size, a runtime error is always thrown.
我的理解是operator new只分配内存,并且不调用任何构造函数,因此placement new用于在内存中的精确空间调用构造函数。如果这些分配的内存地址是已知的,但在内存中不一定是线性的(例如,存储在内存池类的链表中),我会想象有一种合适的方法来释放分配的内存迭代内存地址的链接列表并释放分配大小的内存。但是,通过将内存分配给指向适当大小的数据类型的指针,始终会引发运行时错误。
Is there an appropriate method for doing this?
这样做有适当的方法吗?
Theoretical example:
// 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 个解决方案
#1
6
18.6.1.1/12 (void operator delete(void* ptr) noexcept
):
18.6.1.1/12(void operator delete(void * ptr)noexcept):
Requires:
ptr
shall be a null pointer or its value shall be a value returned by an earlier call to the (possibly replaced)operator new(std::size_t
) oroperator new(std::size_t,const std::nothrow_t&)
which has not been invalidated by an intervening call tooperator delete(void*)
.要求:ptr应为空指针或其值应为先前调用(可能已替换)运算符new(std :: size_t)或operator new(std :: size_t,const std :: nothrow_t&)返回的值。没有被操作员删除(void *)的干预调用无效。
I don't think you can get much more explicit than that with respect to destroying allocated memory in pieces: It's disallowed by the standard.
对于破坏分配的内存而言,我认为你不能比这更明确:标准不允许这样做。
#2
0
If you mean "can the new operator allocate a huge chunk of memory and then return part of it to the caller making memory allocation really efficient" then generally, yes... that's already what happens. With modern systems, you don't even get any memory allocated - what happens is you are allocated a chunk of virtual address space that is backed by real memory only when you write to it, the CPUs MMU handling all this for you.
如果你的意思是“新运算符可以分配大量内存,然后将其中的一部分返回给调用者,使内存分配真正有效”,那么通常,是的......已经发生了什么。使用现代系统,您甚至不会分配任何内存 - 会发生的情况是,您只分配了一块虚拟地址空间,只有在您写入时才由真实内存支持,CPU MMU会为您处理所有这些内容。
What is not supported is allocating memory at the applications code level and trying to free it partially, what you get from new is what you have to use as a single chunk.
不支持的是在应用程序代码级别分配内存并尝试部分释放内存,从new获得的内容是您必须将其用作单个块。
#1
6
18.6.1.1/12 (void operator delete(void* ptr) noexcept
):
18.6.1.1/12(void operator delete(void * ptr)noexcept):
Requires:
ptr
shall be a null pointer or its value shall be a value returned by an earlier call to the (possibly replaced)operator new(std::size_t
) oroperator new(std::size_t,const std::nothrow_t&)
which has not been invalidated by an intervening call tooperator delete(void*)
.要求:ptr应为空指针或其值应为先前调用(可能已替换)运算符new(std :: size_t)或operator new(std :: size_t,const std :: nothrow_t&)返回的值。没有被操作员删除(void *)的干预调用无效。
I don't think you can get much more explicit than that with respect to destroying allocated memory in pieces: It's disallowed by the standard.
对于破坏分配的内存而言,我认为你不能比这更明确:标准不允许这样做。
#2
0
If you mean "can the new operator allocate a huge chunk of memory and then return part of it to the caller making memory allocation really efficient" then generally, yes... that's already what happens. With modern systems, you don't even get any memory allocated - what happens is you are allocated a chunk of virtual address space that is backed by real memory only when you write to it, the CPUs MMU handling all this for you.
如果你的意思是“新运算符可以分配大量内存,然后将其中的一部分返回给调用者,使内存分配真正有效”,那么通常,是的......已经发生了什么。使用现代系统,您甚至不会分配任何内存 - 会发生的情况是,您只分配了一块虚拟地址空间,只有在您写入时才由真实内存支持,CPU MMU会为您处理所有这些内容。
What is not supported is allocating memory at the applications code level and trying to free it partially, what you get from new is what you have to use as a single chunk.
不支持的是在应用程序代码级别分配内存并尝试部分释放内存,从new获得的内容是您必须将其用作单个块。