Неправильное освобождение программы C прекращает работу с кучей - PullRequest
2 голосов
/ 30 января 2012

При попытке дважды освободить одну и ту же неправильно распределенную кучу или нераспределенную кучу вы получаете фатальные ошибки «двойное освобождение или повреждение (fasttop)» и «неверный указатель» соответственно, следовательно, работающая программа немедленно прерывается.

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

Ответы [ 5 ]

3 голосов
/ 30 января 2012

Немедленное прерывание максимально увеличивает вероятность того, что вы заметите ошибку и исправите ее.
Ошибки такого рода могут показаться безвредными, но с небольшими изменениями кода они губительны и трудны для отладки.

Учтите это - вы (A) отпускаете указатель p и через некоторое время снова отпускаете его.Между тем, некоторый код (B) сделал malloc и случайно получил тот же адрес.Теперь второй свободный будет в порядке, потому что выделено p.Теперь другой человек (C) делает malloc и снова получает тот же адрес (вполне вероятно, если он того же размера).Когда C пишет в p, он портит данные B.А кто виноват?A. Удачи в его отладке.

Так что в молодости нужно ловить двойную свободу, а не терпеть.

1 голос
/ 30 января 2012

Если у вас есть веская причина разрешить такое поведение, как двойное освобождение указателя, то я предлагаю вам взглянуть на реализацию обработки исключений в C с использованием setjmp и longjmp, но из опыта я был бы более склонен устранить подобную логику.

1 голос
/ 30 января 2012

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

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

Среда выполнения дает вам сеть безопасности, когда это возможно, но не полагайтесь на нее. Если вы запутались в одном из них, отлаживайте его, пока он не будет исправлен.

0 голосов
/ 30 января 2012

Несмотря на то, что это логически некорректно, мне кажется, что работающей программе нет никакого фатального вреда.

Предупреждение об ошибке.Рассмотрим следующее:

  • поток 1 выделяет адрес 42 и записывает в него 'xyzzy'.
  • поток 1 освобождает адрес 42.
  • поток 2 выделяет адрес 42 изапишите в него 'plugh'.
  • поток 1 снова ошибочно освобождает адрес 42.
  • поток 3 выделяет адрес 42 и записывает в него "извилистые маленькие переходы".

Теперь потоки 2 и 3 оба считают, что им принадлежит эта память.Это примерно так же устойчиво, как мой маленький сын и дочь, которые думают, что они владеют той последней игрушкой, которую купили, поэтому, нет, это не закончится хорошо: -)

Имейте в виду, эти "темы«подразумевается, что они не должны быть потоками выполнения в многопоточной среде, это просто различие, которое я использовал, чтобы показать владение памятью.

Хорошая идиома для обработки ошибок:

  • , если вы можете полностью это исправить, сделайте это.
  • , если вы не можете это исправить полностью, остановитесь как можно быстрее, чтобы минимизировать ущерб.
0 голосов
/ 30 января 2012

Рассмотрим следующий код:

    int * i = (int *)malloc(2 * sizeof(int));
    free(i);
    int * j = (int *)malloc(sizeof(int));
    int * k = (int *)malloc(sizeof(int));
    free(i);

Теперь предположим, что j содержит тот же адрес, что и i, а k содержит i + 1. Когда второй free() заказан, вы объявляете весь блок (j, k) свободным, а не просто j (free() фактически знает, сколько памяти он должен объявить свободным). Такое поведение по понятным причинам предосудительно, потому что даже если вы покончили с j, вы можете использовать k в оставшейся части кода.

...