Почему свободный (p) не устанавливает p в NULL?

Любые причины, почему это не может быть стандартным поведением free()?

несколько указателей, указывающих на тот же объект:

#include <stdlib.h>
#include <stdio.h>

void safefree(void*& p)
{
    free(p); p = NULL;
}

int main()
{
    int *p = (int *)malloc(sizeof(int));
    *p = 1234;
    int*& p2 = p;
    printf("p=%p p2=%p\n", p, p2);
    safefree((void*&)p2);
    printf("p=%p p2=%p\n", p, p2);
    safefree((void*&)p); // safe

    return 0;
}

присвоение от malloc бросок требований от void*

наоборот:

safefree() бросок требований к void*& (ссылка)

15
задан phuclv 6 June 2016 в 15:09
поделиться

9 ответов

Если бы это было так, вам пришлось бы передать указатель на указатель на функцию:

int * p = malloc( sizeof( int ));
free( & p );

, что, я уверен, многие ошиблись бы.

28
ответ дан 30 November 2019 в 23:49
поделиться

Что касается цитаты Страуструпа об удалении, Питер Норвиг также делает аналогичное замечание. Он пишет (не о C ++!):

"Nothing is destroyed until it is replaced"
 - Auguste Comte (1798-1857) (on the need for revolutionary new
   theories (or on the need to do x.f = null in garbage-collected
   languages with destructors))

В моем коде на C я считаю очень полезным следующий макрос:

#define free(p) free((void *)(p)),(p)=NULL /* zero p */

Он, как написано, использует свой аргумент дважды. Но это не проблема, так как любое использование типа free (p ++) или free (find_ named_object ("foo")) приведет к ошибке времени компиляции (требуется lvalue). И вы можете скрыть макрос, используя (бесплатно) (p ++) или назвав его как-нибудь еще, например. БЕСПЛАТНО.

2
ответ дан 30 November 2019 в 23:49
поделиться

Простой ответ: возможно, вы освобождаете выражение, например бесплатно (find_ named_object ("foo")) .

Более подробно: функция free принимает параметр void * , который является адресом памяти, которую нужно освободить. Это не дает функции знания об исходной переменной, которая предоставила адрес (или, если на то пошло, о том, существует ли вообще переменная). Простая установка переданного параметра в NULL тоже ничего не даст, поскольку это просто локальная копия адреса.

27
ответ дан 30 November 2019 в 23:49
поделиться

Бьярн Страуструп обсуждает, должен ли оператор удалить обнулить его операнд . Это не функция free (), но в любом случае это хорошее обсуждение. Рассмотрим такие вопросы, как:

  • Что будет обнулено, если вы скажете «свободно» (p + 1)?
  • Что, если есть два указателя на память? Зачем устанавливать только один на null, если висящая ссылка все еще остается?

Он также говорит, что это было задумано, но никогда не произошло с operator delete :

C ++ явно разрешает реализацию удаления до нуля. операнд lvalue, и я надеялся, что реализации это сделают, но эта идея, похоже, не стала популярной среди разработчиков.
15
ответ дан 30 November 2019 в 23:49
поделиться

В C вызов функции никогда не может изменить значение переданных вами параметров, поэтому, если free (p) изменил значение p , установив его на ] NULL , то такое поведение действительно будет очень нестандартным.

2
ответ дан 30 November 2019 в 23:49
поделиться

Поскольку параметры функции передаются по значению в C. То есть, если p == 0x12345, вы передаете '0x12345' в free (), а не p «сам».

5
ответ дан 30 November 2019 в 23:49
поделиться

Приведение ссылки с int * & на void * & не гарантированно работает. int * просто не обязательно должен иметь тот же размер, представление или требования к выравниванию, что и void * .

Правильным решением C ++ было бы использование шаблонов, как предлагает Нил Баттерворт в комментарии. И, очевидно, ни один из этих способов не работает в C - отсюда free () .

0
ответ дан 30 November 2019 в 23:49
поделиться

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

Во-вторых, если бы этот указатель имел какие-либо псевдонимы, программист все равно отвечал бы за обнуление их . Я мог видеть проблемы, вызванные тем, что программисты предполагали, что все ссылки были установлены на NULL.

Наконец, не всегда необходимо устанавливать указатель на NULL. Представьте себе функцию, которая выделяет некоторую память, выполняет некоторую работу и освобождает ее перед возвратом. Я мог видеть, что установка указателя на NULL может показаться неоптимальной.

6
ответ дан 30 November 2019 в 23:49
поделиться

Что это за мания с нулем? Есть же другие числа!

Почему свободный указатель должен содержать ноль больше, чем любое другое выделенное значение?

Практически, в своем коде на C++ я часто использую объекты watchdog и при освобождении указателя сбрасываю его не на ноль, а на watchdog. Это имеет дополнительное преимущество в том, что методы объекта все еще могут быть вызваны с помощью существующего интерфейса и гораздо более безопасно и эффективно, чем сброс указателя на ноль (это позволяет избежать проверки объектов на ноль, я просто вызываю объект).

Если бы функция типа free, скажем zfree(void * & p), устанавливала p в ноль, это запретило бы мой стиль сторожевого пса (или, по крайней мере, не помогло бы).

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

0
ответ дан 30 November 2019 в 23:49
поделиться