2015-03-05 3 views
2

Теоретически, если пространство в памяти было выделено с использованием operator new, можно ли было бы освободить эту память по частям? Например, если void *mem = operator new(sizeof(int)*2) был использован для назначения адреса памяти двум переменным int*, один на mem, а другой на mem+sizeof(int), можно ли освободить память одного, но не другого?Освобождение только части памяти, выделенной «оператором new»

Полагаю, что operator new выделяет память и не вызывает никаких конструкторов, поэтому размещение 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 
+0

@ 0x499602D2 Выделяет, моя ошибка. – Aunvre

+1

нет невозможно. Я полагаю, вы могли бы сделать свой собственный распределитель и освободитель, но зачем усложнять жизнь без причины? – bolov

+0

@bolov Потому что я решил сделать эту работу. – Aunvre

ответ

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*).

Я не думаю, что вы можете получить гораздо более явное, чем это, в отношении уничтожения выделенной памяти в кусках: она запрещена стандартом.

0

Если вы имеете в виду «может ли новый оператор выделить огромный кусок памяти, а затем вернуть часть его, чтобы вызывающий блок действительно выделял выделение памяти», то вообще-то, да ... это уже то, что происходит. В современных системах вы даже не получаете выделенной памяти - что происходит, вам выделяется кусок виртуального адресного пространства, который поддерживается реальной памятью, только когда вы пишете на него, процессоры MMU обрабатывают все это для вас.

Что не поддерживается, выделяет память на уровне кода приложений и пытается частично ее освободить, то, что вы получаете от нового, - это то, что вы должны использовать как единый кусок.

Смежные вопросы