在C语言中释放内存的正确方法

时间:2023-01-02 21:17:36

so I'm trying to understand the whole concept of memory management in C and I was given this code:

所以我试着理解C语言中内存管理的整个概念我得到了这段代码:

int main(int argc, int *argv[]) {
  item *x = NULL;
  x = (item *) malloc (sizeof(item));

  ...

  free_item(&x);
}

void free_item(item **x) {
  free(*x);
  *x = NULL;
}

where item is earlier defined structure. The point, where I get confused is free_item(&x); because when I write free_item(x); and change the function to:

其中项目是前面定义的结构。我搞不懂的是free_item(&x);因为当我写free_item(x)并将函数改为:

void free_item(item *x) {
  free(x);
  x = NULL;
}

the code seems to work the same way as the previous one.

代码的工作方式似乎与前面的代码相同。

So, is there any difference? And if not, is there any reason, why would someone send an adress on a pointer of a structure to a function, which frees this structure?

有什么区别吗?如果没有,为什么有人会在一个结构的指针上发送一个地址给一个函数,这个函数释放了这个结构?

5 个解决方案

#1


3  

Yes. First, I think there's a typo in your modified function. It should be:

是的。首先,我认为在您的修改函数中有一个输入错误。应该是:

void free_item(item *x) {
  free(x);
  x = NULL;
}

Now, for the differences. The free call will succeed, as all it expects is a "pointer-to-type" variable for data which is allocated dynamically on the heap.

现在的差异。*调用将会成功,因为它所期望的是在堆上动态分配的数据的“指针到类型”变量。

The second part, x = NULL, will not work as expected. Remember, in C, when passing an argument to a function, we pass by value always, never by reference. You are being passed a copy of a variable, so x = NULL just sets a temporarily automatically allocated copy of x to NULL, not the actual variable passed as an argument.

第二部分,x = NULL,不会像预期的那样工作。记住,在C中,当向函数传递参数时,我们总是传递值,而不是引用。传递给您的是一个变量的副本,因此x = NULL只是将临时自动分配的x副本设置为NULL,而不是作为参数传递的实际变量。

The original function which you changed does both parts correctly.

您修改的原函数对这两个部分都正确。

#2


0  

  1. In the first case, to modify the content of pointer variable x, you need to pass on using a reference. That's why the &x and the double pointer is being used to free() the memeory which has been allocated from main(). This is correct.

    在第一种情况下,要修改指针变量x的内容,需要使用引用进行传递。这就是为什么要使用&x和双指针来释放从main()分配的memeory。这是正确的。

  2. in second case, a function-local copy of x will be created and passed on to free_item() which will have no impact on the x present in main(). The x = NULL; will have the scope only inside free_item().

    在第二种情况下,将创建一个函数-本地的x副本并将其传递给free_item(),这对main()中的x没有影响。x =零;将只在free_item()中具有作用域。

#3


0  

In your first example you are calling free_item with argument of type pointer to pointer to item (assuming item **x argument).

在您的第一个示例中,您使用类型指针的参数调用free_item(假设项目**x参数)。

In second example point value (main::x) is copied to free_item::x (different scope) and that copied value is set to NULL (and value is discarded afterwards).

在第二个示例中,将point值(main::x)复制到free_item: x(不同范围),并将复制的值设置为NULL(然后将值丢弃)。

Add printf("%p\n", x); to the end of main() (after free_item).

添加printf(" % p \ n ",x);到main()的末尾(在free_item之后)。

With first example you will see NULL and with second x will still be set to address previously stored there.

对于第一个示例,您将看到NULL,对于第二个x,仍然将被设置为先前存储在那里的地址。

In first example, lets say your pointer is on address 0x00400000 and it points to memory allocated at 0x00410000.

在第一个示例中,假设您的指针位于地址0x00400000上,它指向在0x00410000分配的内存。

0x00400000 0x00410000 <- x is stored here
0x00400004 0x00400000 <- tmp described later; point to x
...
0x00410000 .......... <- x points here; start of item - returned by malloc

When you call item **tmp = &x you will see that it will contain the address 0x00400000 (and tmp itself would be stored on different memory address).

当您调用项**tmp = &x时,您将看到它将包含地址0x00400000(而tmp本身将存储在不同的内存地址上)。

Then in free_item():

然后在free_item():

free(*tmp);     // The same as free(0x00410000)
*tmp = NULL;    // Modifies data at 0x00400000 = NULL

#4


-1  

When you use free ,you pass the pointer ,not the value of the pointer.

使用free时,传递的是指针,而不是指针的值。

So, if you use

所以,如果你使用

 item *x

, you should use

,您应该使用

free(x)

#5


-2  

  1. x = (item *) malloc (sizeof(item)); is unnecessary. x = malloc(sizeof(item)); will suffice.
  2. x =(项目*)malloc (sizeof(项目));是不必要的。x = malloc(sizeof(项目));就足够了。

2.

2。

void free_item(item *data){
  free(data);
}

Is the correct way to do it.

是正确的方法。

  1. Write idiomatic C code. There is no difference perse but its hard do debug and maintain.
  2. 写惯用的C代码。虽然没有区别,但是很难调试和维护。

I would write free_item(x); rather than free_item(&x) and have free_item(item **x)

我将写free_item(x);而不是free_item(&x)并拥有free_item(项目**x)

#1


3  

Yes. First, I think there's a typo in your modified function. It should be:

是的。首先,我认为在您的修改函数中有一个输入错误。应该是:

void free_item(item *x) {
  free(x);
  x = NULL;
}

Now, for the differences. The free call will succeed, as all it expects is a "pointer-to-type" variable for data which is allocated dynamically on the heap.

现在的差异。*调用将会成功,因为它所期望的是在堆上动态分配的数据的“指针到类型”变量。

The second part, x = NULL, will not work as expected. Remember, in C, when passing an argument to a function, we pass by value always, never by reference. You are being passed a copy of a variable, so x = NULL just sets a temporarily automatically allocated copy of x to NULL, not the actual variable passed as an argument.

第二部分,x = NULL,不会像预期的那样工作。记住,在C中,当向函数传递参数时,我们总是传递值,而不是引用。传递给您的是一个变量的副本,因此x = NULL只是将临时自动分配的x副本设置为NULL,而不是作为参数传递的实际变量。

The original function which you changed does both parts correctly.

您修改的原函数对这两个部分都正确。

#2


0  

  1. In the first case, to modify the content of pointer variable x, you need to pass on using a reference. That's why the &x and the double pointer is being used to free() the memeory which has been allocated from main(). This is correct.

    在第一种情况下,要修改指针变量x的内容,需要使用引用进行传递。这就是为什么要使用&x和双指针来释放从main()分配的memeory。这是正确的。

  2. in second case, a function-local copy of x will be created and passed on to free_item() which will have no impact on the x present in main(). The x = NULL; will have the scope only inside free_item().

    在第二种情况下,将创建一个函数-本地的x副本并将其传递给free_item(),这对main()中的x没有影响。x =零;将只在free_item()中具有作用域。

#3


0  

In your first example you are calling free_item with argument of type pointer to pointer to item (assuming item **x argument).

在您的第一个示例中,您使用类型指针的参数调用free_item(假设项目**x参数)。

In second example point value (main::x) is copied to free_item::x (different scope) and that copied value is set to NULL (and value is discarded afterwards).

在第二个示例中,将point值(main::x)复制到free_item: x(不同范围),并将复制的值设置为NULL(然后将值丢弃)。

Add printf("%p\n", x); to the end of main() (after free_item).

添加printf(" % p \ n ",x);到main()的末尾(在free_item之后)。

With first example you will see NULL and with second x will still be set to address previously stored there.

对于第一个示例,您将看到NULL,对于第二个x,仍然将被设置为先前存储在那里的地址。

In first example, lets say your pointer is on address 0x00400000 and it points to memory allocated at 0x00410000.

在第一个示例中,假设您的指针位于地址0x00400000上,它指向在0x00410000分配的内存。

0x00400000 0x00410000 <- x is stored here
0x00400004 0x00400000 <- tmp described later; point to x
...
0x00410000 .......... <- x points here; start of item - returned by malloc

When you call item **tmp = &x you will see that it will contain the address 0x00400000 (and tmp itself would be stored on different memory address).

当您调用项**tmp = &x时,您将看到它将包含地址0x00400000(而tmp本身将存储在不同的内存地址上)。

Then in free_item():

然后在free_item():

free(*tmp);     // The same as free(0x00410000)
*tmp = NULL;    // Modifies data at 0x00400000 = NULL

#4


-1  

When you use free ,you pass the pointer ,not the value of the pointer.

使用free时,传递的是指针,而不是指针的值。

So, if you use

所以,如果你使用

 item *x

, you should use

,您应该使用

free(x)

#5


-2  

  1. x = (item *) malloc (sizeof(item)); is unnecessary. x = malloc(sizeof(item)); will suffice.
  2. x =(项目*)malloc (sizeof(项目));是不必要的。x = malloc(sizeof(项目));就足够了。

2.

2。

void free_item(item *data){
  free(data);
}

Is the correct way to do it.

是正确的方法。

  1. Write idiomatic C code. There is no difference perse but its hard do debug and maintain.
  2. 写惯用的C代码。虽然没有区别,但是很难调试和维护。

I would write free_item(x); rather than free_item(&x) and have free_item(item **x)

我将写free_item(x);而不是free_item(&x)并拥有free_item(项目**x)