Вызов 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, поэтому код, который использует ссылку, работает нормально.