Почему мой указатель не равен нулю после освобождения? - PullRequest
9 голосов
/ 30 сентября 2011
void getFree(void *ptr)
{
    if(ptr != NULL)
    {
        free(ptr);
        ptr = NULL;
    }
    return;
}
int main()
{
char *a;
a=malloc(10);
getFree(a);
if(a==NULL)
    printf("it is null");
else
    printf("not null");
}

Почему выходные данные этой программы не равны NULL?

Ответы [ 5 ]

21 голосов
/ 30 сентября 2011

Поскольку указатель копируется по значению в вашу функцию.Вы присваиваете NULL локальной копии переменной (ptr).Это не присваивает его исходной копии.

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

Thisтак же, как если бы вы вместо этого передавали int функции.Вы не ожидаете, что оригинал int будет отредактирован этой функцией, если только вы не передали указатель на него.

void setInt(int someValue) {
    someValue = 5;
}

int main() {
    int someOtherValue = 7;
    setInt(someOtherValue);
    printf("%i\n", someOtherValue); // You'd expect this to print 7, not 5...
    return 0;
}

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

void getFree(void** ptr) {
    /* Note we are dereferencing the outer pointer,
    so we're directly editing the original pointer */

    if (*ptr != NULL) {
        /* The C standard guarantees that free() safely handles NULL,
           but I'm leaving the NULL check to make the example more clear.
           Remove the "if" check above, in your own code */
        free(*ptr);
        *ptr = NULL;
    }

    return;
}

int main() {
    char *a;
    a = malloc(10);

    getFree(&a); /* Pass a pointer-to-pointer */

    if (a == NULL) {
        printf("it is null");
    } else {
        printf("not null");
    }

    return 0;
}
7 голосов
/ 30 сентября 2011

Потому что функция getFree() берет копию указателя. ptr и c являются указателями, но они являются разными переменными. По этой же причине эта функция выведет «6»:

void Magic(int x)
{
    x = 1;
}

void main()
{
    int a = 6;
    Magic(a);
    printf("%d", a);
}
5 голосов
/ 30 сентября 2011

Вы передаете указатель a по значению, поэтому он не изменяется функцией.Это только копия указателя, измененного внутри функции, исходное значение переменной не затронуто.

Обновление:

Если вы хотите упростить свою жизнь, заменив освобождение + обнуление переменной однимстрока кода, вам нужен макрос:

#define MYFREE(x) free(x); x = NULL;

или функция с указателем на аргумент указателя:

void myfree(void** pp) { free(*pp); *pp = NULL; }
3 голосов
/ 30 сентября 2011

Указатели хранятся в виде целых чисел где-то в памяти.

Когда вы делаете a = malloc(10);, a имеет некоторое значение, скажем, 0x1.

Когда вы вызываете getFree(a);, функциякопирует a в void *ptr.

Сейчас a=0x1 и ptr=0x1.

Когда вы делаете ptr=NULL, только ptr изменяется на NULL, но aвсе еще 0x1 ..

1 голос
/ 30 сентября 2011

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

void getFree(void **ptr)
{

    if(*ptr != NULL)
    {
        free(*ptr);
        *ptr = NULL;
    }

    return;
}
...