LINUX.ORG.RU

История изменений

Исправление eao197, (текущая версия) :

Может быть p == q && *p != *q.

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

И в твоём примере компилятор имеет право

if(ptr != NULL) { // (1)

приравнять к

if(false) { // (1)

Потому что условие выше указывает, что если бы ptr != NULL было > истинным, то уже выполнилось бы free, что недопустимо.

А что было бы, если бы free вызывался не прямо в этой функции, а внутри какой-нибудь вспомогательной:

void data_cleanup(data * ptr) {
  if(ptr != NULL) {
    do_cleanup_related_actions(ptr);
  }
  else {
    ... // Какие-то другие действия. Допустим, просто
        // печать в лог о том, что data_cleanup был вызван.
  }

  ... // Еще какие-то действия, которые не зависят от
      // значения ptr.

  // А здесь нужно еще что-то сделать если ptr не был NULL.
  if(ptr != NULL) { // (1)
    ... 
  }
}

где do_cleanup_related_actions – это функция, реализованная в другой единице трансляции.

Более того, do_cleanup_related_actions может быть указателем на функцию, который принимает свое значение уже в run-time.

Исходная версия eao197, :

Может быть p == q && *p != *q.

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

И в твоём примере компилятор имеет право if(ptr != NULL) { // (1) приравнять к if(false) { // (1) Потому что условие выше указывает, что если бы ptr != NULL было > истинным, то уже выполнилось бы free, что недопустимо.

А что было бы, если бы free вызывался не прямо в этой функции, а внутри какой-нибудь вспомогательной:

void data_cleanup(data * ptr) {
  if(ptr != NULL) {
    do_cleanup_related_actions(ptr);
  }
  else {
    ... // Какие-то другие действия. Допустим, просто
        // печать в лог о том, что data_cleanup был вызван.
  }

  ... // Еще какие-то действия, которые не зависят от
      // значения ptr.

  // А здесь нужно еще что-то сделать если ptr не был NULL.
  if(ptr != NULL) { // (1)
    ... 
  }
}

где do_cleanup_related_actions – это функция, реализованная в другой единице трансляции.

Более того, do_cleanup_related_actions может быть указателем на функцию, который принимает свое значение уже в run-time.