Foo* set = new Foo[100];
// ...
delete [] set;
Вы не передаете границы массива в delete[]
. Но где хранится эта информация? Стандартизировано ли оно?
Foo* set = new Foo[100];
// ...
delete [] set;
Вы не передаете границы массива в delete[]
. Но где хранится эта информация? Стандартизировано ли оно?
Когда вы выделяете память в куче, ваш распределитель будет отслеживать, сколько памяти вы выделили. Обычно это хранится в сегменте "голова" непосредственно перед памятью, которую вы получаете. Таким образом, когда он освобождает память, де-распределитель точно знает, сколько памяти освободится.
ОДИН из подходов для компиляторов заключается в том, чтобы выделить немного больше памяти и сохранить количество элементов в элементе head.
Пример того, как это можно сделать:
Здесь
int* i = new int[4];
компилятор выделяет sizeof(int)*5
байты.
int *temp = malloc(sizeof(int)*5)
Будет хранить "4" в первом sizeof(int)
байтах
*temp = 4;
и установите i
i = temp + 1;
Итак, i
будет указывать на массив из 4 элементов, а не на 5.
И удаление
delete[] i;
будет обрабатываться следующим образом:
int *temp = i - 1;
int numbers_of_element = *temp; // = 4
... call destructor for numbers_of_element elements
... that are stored in temp + 1, temp + 2, ... temp + 4 if needed
free (temp)
Информация не стандартизирована. Однако на платформах, над которыми я работал над этой информацией, хранится в памяти непосредственно перед первым элементом. Поэтому вы могли бы теоретически получить доступ к нему и проверить его, однако это не стоит.
Также вы должны использовать delete [], когда вы выделили память с помощью нового [], так как версия версии delete знает, что (и где) нужно искать, чтобы освободить нужный объем памяти - и вызвать соответствующий количество деструкторов для объектов.
В основном его расположение в памяти:
[info] [mem вы просили...]
Где информация - это структура, используемая вашим компилятором для хранения объема выделенной памяти, а что нет.
Это зависит от реализации.
Это не то, что зависит от зависимостей спецификации.
Он определен в стандарте С++ для специфики компилятора. Что означает магия компилятора. Он может сломаться с нетривиальными ограничениями выравнивания, по крайней мере, на одной из основных платформ.
Вы можете думать о возможных реализациях, понимая, что delete[]
определяется только для указателей, возвращаемых new[]
, которые могут не совпадать с указателем, возвращаемым operator new[]
. Одна из реализаций в дикой природе состоит в том, чтобы сохранить количество массивов в первом int, возвращаемом operator new[]
, и new[]
вернуть обратно смещение указателя. (Вот почему нетривиальные выравнивания могут сломаться new[]
.)
Имейте в виду, что operator new[]/operator delete[]
!= new[]/delete[]
.
Плюс, это ортогонально тому, как C знает размер памяти, выделенный malloc
.
Поскольку массив, который нужно удалить, должен был быть создан с использованием только одного оператора new. "Новая" операция должна была помещать эту информацию в кучу. В противном случае, как дополнительные виды использования нового знают, где заканчивается куча?
Это не стандартизировано. В среде выполнения Microsoft новый оператор использует malloc(), а оператор delete использует free(). Итак, в этой настройке ваш вопрос эквивалентен следующему: как free() знает размер блока?
Существует некоторая бухгалтерия, идущая за кулисами, т.е. во время выполнения C.
Это более интересная проблема, чем вы могли бы подумать вначале. Этот ответ касается одной возможной реализации.
Во-первых, хотя на каком-то уровне ваша система должна знать, как "освобождать" блок памяти, базовый malloc/free (который обычно вызывает /new/delete/new []/delete []) не всегда помнит точно сколько памяти вы просите, его можно округлить (например, если вы выше 4K, он часто округляется до следующего блока размером 4 КБ).
Следовательно, даже если бы он мог получить размер блока памяти, это не говорит нам, сколько значений находится в новой [] памяти, так как оно может быть меньше. Поэтому нам нужно сохранить дополнительное целое число, сообщающее нам, сколько значений есть.
ЗА ИСКЛЮЧЕНИЕМ, если построенный тип не имеет деструктора, тогда delete [] не должен ничего делать, кроме освобождения блока памяти, и поэтому ему не нужно ничего хранить!