Как узнать, является ли адрес, указанный в free (), недействительным? - PullRequest
4 голосов
/ 28 июня 2011

Есть ли способ узнать, является ли адрес, указанный в free( ), неверным адресом, перед вызовом free( )?

Мы знаем, free( ) создает неопределенное поведение, если адрес является недействительным (уже освобожденный адрес). Так как же убедиться, что этот адрес является действительным?

Заранее спасибо.

Ответы [ 4 ]

6 голосов
/ 28 июня 2011

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

Вы можете обнаружить, что Valgrind может помочь вам понять, где что-то идет не так.

2 голосов
/ 28 июня 2011

Нет .

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

Если вы используете те же указатели, чтобы иногда ссылаться на память, полученную с помощью malloc, а в других случаях ссылаться на строковые литералы или автоматические переменные, тогда вы должны просто сохранить флаг рядом с указателем, который указывает, указывает ли он на что-то полученное malloc. Или вы можете просто сохранить вторую копию указателя с именем ptr_to_free, это NULL, когда данные не нуждаются в освобождении. Это также имеет то преимущество, что ваш «основной указатель» может «перемещаться» и указывать на разные части объекта, поскольку вы будете сохранять исходный / базовый указатель свободным отдельно.

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

2 голосов
/ 28 июня 2011

Поведение на free() для недопустимого адреса не определено, поскольку оно непредсказуемо.На языке низкого уровня, таком как C, вы не можете сказать, является ли адрес «действительным» или «недействительным».И есть много причин, по которым адрес может быть недействительным.«Уже освобожден» - это только один из других случаев, в том числе: адрес, не выделенный malloc, данные на самом деле не являются адресом (например, некоторое целое число или строка символов, приведенная к указателю), повреждение данных и т. Д.

ЕслиВы заинтересованы в «уже освобожденном» случае, только вы можете попытаться отследить каждое выделение и освобождение памяти (например, с помощью пользовательской оболочки malloc() и free()), но это, вероятно, только сделает ваш код более сложным и еще более ошибочным-prone.

Простой ответ: нет, нет способа проверить, является ли адрес недействительным.Жить с ним или переключиться на язык более высокого уровня (например, Python), когда вам вообще не нужны адреса памяти.

0 голосов
/ 28 июня 2011

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

Я бы также предложил следующие указатели.

  1. Инициализация указателяв NULL, пока вы объявляете его
  2. После освобождения вы инициализируете его снова в NULL
  3. Проверьте, не равен ли указатель NULL, прежде чем пытаться освободить.
...