Вызов delete по адресу переменной
Почему я могу сделать:
int i = *(new int (5));
И успешно использовать i
после него,
Но когда я пытаюсь:
delete &i;
Я получаю ошибку времени выполнения:
Необработанное исключение при 0x5ddccaf7 (msvcr100d.dll) в тесте.exe: 0xC00000FD: переполнение стека.
Если i
была ссылка:
int & i = *(new int (5));
, все это (включая delete
) прекрасно работает.
Я знаю, что нехорошо хранить выделенный обработчик памяти в чем-то другом, кроме указателя, и *(new ...)
является ужасно, но мне просто интересно, почему new
работает хорошо, но delete
терпит неудачу.
//ниже приведены лишь мои догадки о причине такого поведения:
Это потому, что модуль, который выполняет программу (это, вероятно, не "компилятор", потому что уже есть время выполнения ), когда он сталкивается с delete
, он ищет некоторую информацию, такую как длина данных, указывающих на &i
(в некотором внутреннем массиве такой информации обо всех указателях), и не находит ее или интерпретирует какой-то мусор данные как эта информация? (Я полагаю, что указатели и ссылки имеют его, но переменные-нет)
3 ответа:
Ваша исходная версия не присваивает
i
Адрес. Он выделяет новый int в куче и инициализирует его значение до 5, а затем копирует это значение вi
, который находится в стеке. Выделенная Вами память (new
'ed) недоступна и получает утечку.Эталонная версия работает потому, что
i
ссылается на иначе анонимную памятьnew
'ed. Следовательно,&i
дает адрес кучи. В вашей первой версии&i
задает адрес переменной стека, а не Памяти кучи, и удаление стековой памяти-плохая новость.
Вы получаете ошибку времени выполнения, потому что адрес
i
не совпадает с адресом, возвращаемым операторомnew
. Как только вы разыменуете результатnew
, вы сделаете копию значения. Эта копия затем помещается в переменнуюi
, которая имеет адрес в автоматическом хранилище, который не может быть переданdelete
законно без запуска неопределенного поведения.Когда вы делаете ссылку, однако, вы не делаете копию: результат
new
становится ссылочным через a переменнаяi
типа " ссылка наint
". Следовательно, ссылка имеет тот же адрес, который был возвращенoperator new
, поэтому код, который использует ссылку, работает нормально.