Вызов 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 4

3 ответа:

Ваша исходная версия не присваивает i Адрес. Он выделяет новый int в куче и инициализирует его значение до 5, а затем копирует это значение в i, который находится в стеке. Выделенная Вами память (new'ed) недоступна и получает утечку.

Эталонная версия работает потому, что i ссылается на иначе анонимную память new'ed. Следовательно, &i дает адрес кучи. В вашей первой версии &i задает адрес переменной стека, а не Памяти кучи, и удаление стековой памяти-плохая новость.

Вы получаете ошибку времени выполнения, потому что адрес i не совпадает с адресом, возвращаемым оператором new. Как только вы разыменуете результат new, вы сделаете копию значения. Эта копия затем помещается в переменную i, которая имеет адрес в автоматическом хранилище, который не может быть передан delete законно без запуска неопределенного поведения.

Когда вы делаете ссылку, однако, вы не делаете копию: результат new становится ссылочным через a переменная i типа " ссылка на int". Следовательно, ссылка имеет тот же адрес, который был возвращен operator new, поэтому код, который использует ссылку, работает нормально.

Строка:

int i = *(new int (5));

Эквивалентно:

int* p = new int(5);
int i = *p;

Адрес i (который вы пытаетесь delete) не является адресом выделенной памяти.

В математической нотации &x == &y подразумевает x == y, но x == y не подразумевает &x == &y.