Как delete [] «знает» размер массива операндов? - PullRequest
219 голосов
/ 13 октября 2008
Foo* set = new Foo[100];
// ...
delete [] set;

Вы не передаете границы массива delete[]. Но где хранится эта информация? Это стандартизировано?

Ответы [ 9 ]

151 голосов
/ 13 октября 2008

Когда вы распределяете память в куче, ваш распределитель будет отслеживать, сколько памяти вы выделили. Обычно он хранится в «головном» сегменте непосредственно перед выделенной вам памятью. Таким образом, когда пришло время освободить память, де-распределитель точно знает, сколько памяти освободить.

19 голосов
/ 24 февраля 2014

Один из подходов для компиляторов - выделить немного больше памяти и сохранить количество элементов в элементе 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)
9 голосов
/ 13 октября 2008

Информация не стандартизирована. Однако на платформах, над которыми я работал, эта информация хранится в памяти непосредственно перед первым элементом. Поэтому теоретически вы можете получить к нему доступ и проверить его, однако это того не стоит.

Также именно поэтому вы должны использовать delete [], когда вы выделяете память новым [], поскольку версия массива delete знает, что (и где) нужно искать, чтобы освободить нужный объем памяти, и вызывать соответствующий количество деструкторов для объектов.

5 голосов
/ 16 октября 2008

В основном это расположено в памяти как:

[info] [mem вы просили ...]

Где информация - это структура, используемая вашим компилятором для хранения объема выделенной памяти, а что нет.

Это зависит от реализации.

3 голосов
/ 13 октября 2008

Это не то, что в спецификации - это зависит от реализации.

2 голосов
/ 16 октября 2008

В стандарте C ++ определено, что оно зависит от компилятора. Что означает магию компилятора. Он может сломаться с нетривиальными ограничениями выравнивания хотя бы на одной основной платформе.

Вы можете думать о возможных реализациях, понимая, что delete[] определяется только для указателей, возвращаемых new[], которые могут не совпадать с указателями, возвращаемыми operator new[]. Одной из реализаций в дикой природе является сохранение числа массивов в первом int, возвращаемом operator new[], и new[], возвращающем смещение указателя после этого. (Вот почему нетривиальные выравнивания могут нарушаться new[].)

Имейте в виду, что operator new[]/operator delete[]! = new[]/delete[].

Плюс, это ортогонально тому, как C знает размер памяти, выделенной malloc.

2 голосов
/ 13 октября 2008

Поскольку массив, который нужно «удалить», должен был быть создан с использованием оператора «new» за один раз. «Новая» операция должна была поместить эту информацию в кучу. Иначе как дополнительные пользователи new узнают, где заканчивается куча?

0 голосов
/ 14 ноября 2015

Это более интересная проблема, чем вы думаете на первый взгляд. Этот ответ об одной возможной реализации.

Во-первых, хотя на каком-то уровне ваша система должна знать, как «освободить» блок памяти, лежащий в основе malloc / free (который обычно вызывают new / delete / new [] / delete []) не всегда точно запоминает сколько памяти вы запрашиваете, она может быть округлена (например, когда вы выше 4K, она часто округляется до следующего блока размером 4K).

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

КРОМЕ, если конструируемый тип не имеет деструктора, тогда delete [] не должен делать ничего, кроме освобождения блока памяти, и, следовательно, не должен ничего хранить!

0 голосов
/ 13 октября 2008

не нормируется. Во время выполнения Microsoft новый оператор использует malloc (), а оператор удаления - free (). Итак, в этой настройке ваш вопрос эквивалентен следующему: Как free () узнает размер блока?

За кулисами ведется некоторая бухгалтерия, т. Е. В среде выполнения C.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...