为什么free后我的指针不是null?

15
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?


6
在使用free函数时,其前面的条件判断是不必要的。直接调用free(0)也完全没有问题。 - Kerrek SB
6个回答

27

由于指针是 按值传递 到您的函数中的。您正在将 NULL 分配给变量的本地副本 (ptr)。这并不会将其分配给原始副本。

内存仍将被释放,因此您无法再安全访问它,但是您原始的指针不会成为 NULL

这与如果您将一个 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;
}
如果您想将原始指针置空(null),则需要传递一个指向指针的指针。
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

因为getFree()函数会复制指针。ptrc 都是指针,但它们是不同的变量。这也是为什么这个函数将输出“6”的原因:

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

void main()
{
    int a = 6;
    Magic(a);
    printf("%d", a);
}

5

您正在通过值传递指针a,因此它不会被函数修改。仅在函数内部修改指针的副本,原始变量值不受影响。

更新:

如果您想通过一行代码来替换释放并将变量置为空,您需要使用宏:

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

或者一个带指向指针参数的函数:
void myfree(void** pp) { free(*pp); *pp = NULL; }

“getFree”函数无法访问原始变量,它只能修改堆栈上的“a”的副本。 - Roman R.
C语言中不存在引用。 - Corbin
+1 是为了确保你明白我现在正在做什么..!! 我将使用您的宏。 - Jeegar Patel
@Corbin:感谢您的纠正,我也怀疑这一点,所以还有其他两个选项可供选择。 - Roman R.
正如Corbin所提到的,这并不是事实。我会编辑答案。 - Roman R.
大多数情况下是个人偏好(尽管宏的误用可能会导致难以找到的错误,而且宏很容易被误用),但我可能会使用内联函数而不是宏。 - Corbin

3
指针存储在内存中的某个整数位置。
当您执行 a = malloc(10); 时,a 具有某个值,比如说 0x1。
当您调用 getFree(a) 时,该函数将 a 复制到 void *ptr 中。
现在,a=0x1,而 ptr=0x1
当您执行 ptr=NULL 时,只有 ptr 被更改为 NULL,但是 a 仍然是 0x1。

1

您正在按值传递指针..(默认情况下,C通过值传递参数),这意味着您仅更新副本..而不是真实位置..为此,您可能需要在C中使用指向指针的指针

void getFree(void **ptr)
{

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

    return;
}

2
这个答案不符合问题。Mr.32 不仅仅是调用 free - undur_gongor
我想我读错了,抱歉。我已经更正了,请检查一下:D - Aman Agarwal

1
这个问题已经有了答案,但如果有帮助的话,我可以用图示来解释一下。 你正在做这个 --> 指针按值复制到你的函数中,所以它指向数组 但是你想要这个 --> 指向原始指针
正如Merlyn Morgan-Graham已经说过的那样,解决这个问题的方法是添加 * 和 & 运算符。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接