当使用free()释放内存时,指针指向的内容为什么没有更改?

时间:2022-03-01 01:02:49

I am a newbie when it comes to dynamic memory allocation. When we free the memory using void free(void *ptr) the memory is deallocated but the contents of the pointer are not deleted. Why is that? Is there any difference in more recent C compilers?

说到动态内存分配,我是个新手。当我们使用void free(void *ptr)释放内存时,内存被释放,但是指针的内容没有被删除。这是为什么呢?最近的C编译器有什么不同吗?

5 个解决方案

#1


8  

Computers don't "delete" memory as such, they just stop using all references to that memory cell and forget that anything of value is stored there. For example:

计算机不会“删除”内存,它们只是停止使用对内存单元的所有引用,而忘记任何有价值的东西都存储在那里。例如:

int* func (void)
{
  int x = 5;
  return &x;
}

printf("%d", *func()); // undefined behavior

Once the function has finished, the program stops reserving the memory location where x is stored, any other part of the program (or perhaps another program) is free to use it. So the above code could print 5, or it could print garbage, or it could even crash the program: referencing the contents of a memory cell that has ceased to be valid is undefined behavior.

一旦函数完成,程序就停止保存存储x的内存位置,程序的任何其他部分(或者其他程序)都可以*使用它。因此,上面的代码可以打印5,或者它可以打印垃圾,或者它甚至可以破坏程序:引用已停止有效的内存单元的内容是未定义的行为。

Dynamic memory is no exception to this and works in the same manner. Once you have called free(), the contents of that part of the memory can be used by anyone.

动态内存也不例外,以同样的方式工作。调用了free()之后,该内存部分的内容可以被任何人使用。

Also, see this question.

同时,看到这个问题。

#2


3  

The thing is that accessing memory after it has been freed is undefined behavior. It's not only that the memory contents are undefined, accessing them could lead to anything. At least some compilers when you build a debug version of the code, actually do change the contents of the memory to aid in debugging, but in release versions it's generally unnecessary to do that, so the memory is just left as is, but anyway, that is not something you can safely rely upon, don't access freed memory, it's unsafe!

问题是在释放内存之后访问内存是未定义的行为。不仅内存内容没有定义,访问它们还可能导致任何结果。至少有一些编译器构建一个调试版本的代码时,确实改变记忆,能够帮助你调试的内容,但在发布版本通常是不必要的,记忆是刚刚离开,但无论如何,这并不是你可以安全地依靠的东西,不释放内存的访问,它是不安全的!

#3


1  

In C, parameters are passed by value. So free just can't change the value of ptr.
Any change it would make would only change the value within the free function, and won't affect the caller's variable.

在C中,参数通过值传递。所以free不能改变ptr的值。它所做的任何改变都只会改变*函数中的值,不会影响调用者的变量。

Also, changing it won't be so much help. There can be multiple pointers pointing to the same piece of memory, and they should all be reset when freeing. The language can't keep track of them all, so it leaves the programmer to handle the pointers.

而且,改变它也不会有多大帮助。可以有指向同一块内存的多个指针,它们在释放时都应该重置。这种语言不能跟踪所有的指针,所以程序员只能处理指针。

#4


1  

This is very normal, because clearing the memory location after free is an overhead and generally not necessary. If you have security concerns, you can wrap the free call within a function which clears the region before freeing. You'll also notice that this requires the knowledge of the allocation size, which is another overhead.

这是非常正常的,因为在空闲之后清除内存位置是一种开销,通常不需要这样做。如果您有安全问题,可以将免费调用包装在一个函数中,该函数在释放之前清除该区域。您还会注意到,这需要对分配大小的知识,这是另一个开销。

#5


1  

Actually the C programming language specifies that after the lifetime of the object, even the value of any pointer pointing to it becomes indeterminate, i.e. you can't even depend on the pointer to even retain the original value.

实际上,C编程语言规定,在对象的生命周期之后,甚至指向它的任何指针的值都变得不确定,也就是说,您甚至不能依赖指针来保持原始值。

That is because a good compiler will try to aggressively store all the variables into the CPU registers instead of memory. So after it sees that the program flow calls a function named free with the argument ptr, it can mark the register of the ptr free for other use, until it has been assigned to again, for example ptr = malloc(42);.

这是因为优秀的编译器会尽量将所有变量存储到CPU寄存器中,而不是内存中。因此,当程序流看到使用参数ptr调用一个名为free的函数后,它可以将ptr的寄存器标记为free,以供其他使用,直到它再次被赋值,例如ptr = malloc(42);

In between these two it could be seen changing the value, or comparing inequal against its original value, or other similar behaviour. Here's an example of what might happen.

在这两者之间,可以看到它改变了价值,或与它的原始价值或其他类似的行为相比。这里有一个可能发生的例子。

#1


8  

Computers don't "delete" memory as such, they just stop using all references to that memory cell and forget that anything of value is stored there. For example:

计算机不会“删除”内存,它们只是停止使用对内存单元的所有引用,而忘记任何有价值的东西都存储在那里。例如:

int* func (void)
{
  int x = 5;
  return &x;
}

printf("%d", *func()); // undefined behavior

Once the function has finished, the program stops reserving the memory location where x is stored, any other part of the program (or perhaps another program) is free to use it. So the above code could print 5, or it could print garbage, or it could even crash the program: referencing the contents of a memory cell that has ceased to be valid is undefined behavior.

一旦函数完成,程序就停止保存存储x的内存位置,程序的任何其他部分(或者其他程序)都可以*使用它。因此,上面的代码可以打印5,或者它可以打印垃圾,或者它甚至可以破坏程序:引用已停止有效的内存单元的内容是未定义的行为。

Dynamic memory is no exception to this and works in the same manner. Once you have called free(), the contents of that part of the memory can be used by anyone.

动态内存也不例外,以同样的方式工作。调用了free()之后,该内存部分的内容可以被任何人使用。

Also, see this question.

同时,看到这个问题。

#2


3  

The thing is that accessing memory after it has been freed is undefined behavior. It's not only that the memory contents are undefined, accessing them could lead to anything. At least some compilers when you build a debug version of the code, actually do change the contents of the memory to aid in debugging, but in release versions it's generally unnecessary to do that, so the memory is just left as is, but anyway, that is not something you can safely rely upon, don't access freed memory, it's unsafe!

问题是在释放内存之后访问内存是未定义的行为。不仅内存内容没有定义,访问它们还可能导致任何结果。至少有一些编译器构建一个调试版本的代码时,确实改变记忆,能够帮助你调试的内容,但在发布版本通常是不必要的,记忆是刚刚离开,但无论如何,这并不是你可以安全地依靠的东西,不释放内存的访问,它是不安全的!

#3


1  

In C, parameters are passed by value. So free just can't change the value of ptr.
Any change it would make would only change the value within the free function, and won't affect the caller's variable.

在C中,参数通过值传递。所以free不能改变ptr的值。它所做的任何改变都只会改变*函数中的值,不会影响调用者的变量。

Also, changing it won't be so much help. There can be multiple pointers pointing to the same piece of memory, and they should all be reset when freeing. The language can't keep track of them all, so it leaves the programmer to handle the pointers.

而且,改变它也不会有多大帮助。可以有指向同一块内存的多个指针,它们在释放时都应该重置。这种语言不能跟踪所有的指针,所以程序员只能处理指针。

#4


1  

This is very normal, because clearing the memory location after free is an overhead and generally not necessary. If you have security concerns, you can wrap the free call within a function which clears the region before freeing. You'll also notice that this requires the knowledge of the allocation size, which is another overhead.

这是非常正常的,因为在空闲之后清除内存位置是一种开销,通常不需要这样做。如果您有安全问题,可以将免费调用包装在一个函数中,该函数在释放之前清除该区域。您还会注意到,这需要对分配大小的知识,这是另一个开销。

#5


1  

Actually the C programming language specifies that after the lifetime of the object, even the value of any pointer pointing to it becomes indeterminate, i.e. you can't even depend on the pointer to even retain the original value.

实际上,C编程语言规定,在对象的生命周期之后,甚至指向它的任何指针的值都变得不确定,也就是说,您甚至不能依赖指针来保持原始值。

That is because a good compiler will try to aggressively store all the variables into the CPU registers instead of memory. So after it sees that the program flow calls a function named free with the argument ptr, it can mark the register of the ptr free for other use, until it has been assigned to again, for example ptr = malloc(42);.

这是因为优秀的编译器会尽量将所有变量存储到CPU寄存器中,而不是内存中。因此,当程序流看到使用参数ptr调用一个名为free的函数后,它可以将ptr的寄存器标记为free,以供其他使用,直到它再次被赋值,例如ptr = malloc(42);

In between these two it could be seen changing the value, or comparing inequal against its original value, or other similar behaviour. Here's an example of what might happen.

在这两者之间,可以看到它改变了价值,或与它的原始价值或其他类似的行为相比。这里有一个可能发生的例子。