Что происходит, когда вы освобождаете указатель дважды или больше в C ++? - PullRequest
23 голосов
/ 30 апреля 2010
int main(){
Employee *e = new Employee();

delete e;
delete e;
...
delete e;
return 0;

}

Ответы [ 7 ]

38 голосов
/ 30 апреля 2010

e это не ссылка, это указатель. Вы получите неопределенное поведение , если попытаетесь delete объект через указатель более одного раза.

Это означает, что в значительной степени может случиться что угодно: от «появления на работе» до «падения» или чего-то совершенно случайного.

18 голосов
/ 30 апреля 2010

Это неопределенное поведение, так что может случиться что угодно.

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

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

11 голосов
/ 30 апреля 2010

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

4 голосов
/ 30 апреля 2010

Вы, вероятно, рискуете проникнуть на территорию "неопределенного поведения".

Во многих системах это вызовет сбой; например, на моей машине с Linux:

*** glibc detected *** ./cctest: double free or corruption (fasttop): 0x0000000000d59900 ***
======= Backtrace: =========
/lib/libc.so.6[0x7f399f4cbdd6]
/lib/libc.so.6(cfree+0x6c)[0x7f399f4d074c]
./cctest[0x400a7a]
/lib/libc.so.6(__libc_start_main+0xfd)[0x7f399f474abd]
./cctest[0x400959]
3 голосов
/ 01 мая 2010

Если вы беспокоитесь, что это может произойти в ваших приложениях, либо полностью прекратите использовать необработанные указатели, чтобы вам не нужно было удалять (например, переключитесь на shared_ptr), либо всегда устанавливайте указатели на NULL (или 0, или еще лучше nullptr) после их удаления. Вызов delete для нулевого указателя гарантированно ничего не сделает.

3 голосов
/ 30 апреля 2010

Если вам действительно повезет, он рухнет. Обычно происходит накопление кармы, пока ваш генеральный директор не покажет код вашему наиболее важному новому клиенту, когда он испортит / уничтожит все их данные.

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

2 голосов
/ 30 апреля 2010

Это небезопасно и не определено, что на самом деле может произойти:

http://www.parashift.com/c++-faq-lite/freestore-mgmt.html#faq-16.2

...