проверка на NULL перед звонком бесплатно - PullRequest
20 голосов
/ 16 декабря 2009

Многие вызовы указателей освобождения кода C:

if (p)
  free(p);

Но почему? Я думал, что стандарт C говорит, что функция free ничего не делает с указателем NULL. Так зачем еще одна явная проверка?

Ответы [ 8 ]

18 голосов
/ 16 декабря 2009

Конструкция:

free(NULL);

всегда был в порядке в C, вернемся к оригинальному компилятору UNIX, написанному Деннисом Ричи. Предварительная стандартизация, некоторые плохие компиляторы, возможно, не предоставили это правильно, но в наши дни любой компилятор, который не может на законных основаниях называть себя компилятором для языка Си. Его использование обычно приводит к созданию более понятного и более удобного кода.

13 голосов
/ 16 декабря 2009

Как я понимаю, запрет на NULL был не всегда.

В старые добрые времена C (назад вокруг 1986, по предварительному стандарту ANSI cc компилятор) бесплатно (NULL) будет дамп ядра. Так что большинство разработчиков тестировалось на NULL / 0 раньше звонок бесплатный.

Мир прошел долгий путь, и это Похоже, нам не нужно делать проверить больше. Но старые привычки умирают трудно;)

http://discuss.joelonsoftware.com/default.asp?design.4.194233.15

6 голосов
/ 16 декабря 2009

Я часто пишу "if (p) free(p)", даже если знаю, что это не нужно.

Я частично обвиняю себя, потому что я узнал C в старые времена, когда free(NULL) мог бы стать причиной ошибки, и я все еще чувствую себя неловко, не делая этого.

Но я также обвиняю стандарт C в несогласованности. Если бы, например, fclose (NULL) был бы хорошо определен, у меня не было бы проблем с написанием:

free(p);
fclose(f);

Что часто случается при очистке вещей. К сожалению, мне кажется странным писать

free(p);
if (f) fclose(f);

и я получаю

if (p) free(p);
if (f) fclose(f);

Я знаю, это не рациональная причина, но это мой случай:)

2 голосов
/ 28 мая 2013

Компиляторы, даже если встраивание недостаточно умны, чтобы знать, что функция вернется немедленно. Загрузка параметров и т. Д. В стек и установка вызова, очевидно, дороже, чем тестирование указателя. Я думаю, что всегда полезно избегать выполнения чего-либо, даже если это что-то не работает. Тестирование на ноль - хорошая практика. Еще лучшая практика - убедиться, что ваш код не достигает этого состояния, и, следовательно, полностью исключить необходимость в тестировании.

1 голос
/ 24 апреля 2016

Существует две причины, по которым переменная-указатель может быть NULL:

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

  2. , поскольку он указывает на массив и, следовательно, может иметь значение NULL, если массив имеет нулевую длину (поскольку malloc(0) разрешено возвращать NULL, определяется реализацией).

Хотя это только логическое различие (в C нет ни типов опций , ни специальных указателей на массивы и мы просто используем указатели для всего), это всегда должно быть ясно как переменная используется.

То, что стандарт C требует free(NULL), чтобы ничего не делать, является необходимым аналогом того факта, что успешный вызов malloc(0) может вернуть NULL. Это не является общим удобством, поэтому, например, fclose() требует аргумент, отличный от NULL. Злоупотребление разрешением на вызов free(NULL) путем передачи значения NULL, которое не представляет массив нулевой длины, кажется хакерским и неправильным.

1 голос
/ 16 декабря 2009

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

0 голосов
/ 19 февраля 2018
if (p)
    free(p);

зачем еще одна явная проверка?

Если I напишет что-то подобное, то для передачи конкретных знаний, что указатель может быть НЕДЕЙСТВИТЕЛЕН ... чтобы помочь в удобочитаемости и понимании кода. Потому что это выглядит немного странно, чтобы утверждать это:

assert(p || !p);
free(p);

(Помимо того, что выглядят странно, компиляторы, как известно, жалуются на «условие всегда истинно», если вы включаете предупреждения во многих таких случаях.)

Так что я считаю это хорошей практикой, если это не ясно из контекста.

Обратный случай, когда указатель ожидается не ноль, обычно очевиден из предыдущих строк кода:

...
Unhinge_Widgets(p->widgets);
free(p); // why `assert(p)`...you just dereferenced it!
...

Но если это неочевидно, утверждение может стоить напечатанных символов.

0 голосов
/ 16 декабря 2009

Если вы полагаетесь на то, что free (0) в порядке, и это нормально, когда ваш указатель на этом этапе равен нулю, пожалуйста, сообщите об этом в комментарии // may be NULL

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...