free不会删除分配给指针(int数组)的内存,使用free两次即可,为什么?

时间:2022-07-21 21:17:23

This is out of curiosity, I tried to find answers to my doubt on previous questions but they don't seem to have answer to it. So asking here, I just wrote a code where I am trying to allocate memory to an int pointer (to fill up an array) and scan int values to it. Once I am done with the array, I want to delete the data/memory allocated to the pointer. Although my code works fine and everything, why am I still able to see values inside int array even after freeing the pointer. Whereas, if I use free twice it throws up an error (which was expected after single use of free). Isn't this an odd behavior ? I tried it on my mac using Xcode also on codechef, same behavior, why ?

这是出于好奇,我试着在之前的问题上找到我的疑问的答案,但是他们似乎没有答案。在这里,我写了一段代码,试图将内存分配给int指针(用来填充数组)并扫描int值。完成数组之后,我想要删除分配给指针的数据/内存。虽然我的代码运行得很好,但是为什么我仍然能够在释放指针之后看到int数组中的值。然而,如果我使用两次免费,它会抛出一个错误(这是在一次免费使用之后的预期)。这不是一种奇怪的行为吗?我在我的mac上用Xcode也用codechef试过,同样的行为,为什么?

int *num=(int *)malloc(n*sizeof(int));
int i;
for(i=0;i<n;i++)
{
    scanf("%d",&num[i]);        
}    

for(i=0;i<n-1;i++){
    temp = some_function(x);        
}

free(num); 

for(i=0;i<n;i++)
{
    printf("\nnum[%d]= %d\n",i,num[i]);        
}

The above code prints values inside num[] which ideally it shouldn't.

上面的代码在num[]中打印值,理想情况下不应该这样做。

4 个解决方案

#1


9  

This is not odd, or wrong. When calling free on a pointer, you only tell the memory manager that it can re-use that portion of memory again for another malloc call. It won't erase the contents (this would take extra time with no function whatsoever). But, you can access it, because the pointer still points to a valid address. It leads to undefined behaviour though, because the memory manager could have given that memory to some other piece of code.

这不是奇怪的,也不是错误的。当在指针上调用free时,您只能告诉内存管理器,它可以再次为另一个malloc调用重用该内存部分。它不会删除内容(这需要额外的时间,没有任何函数)。但是,您可以访问它,因为指针仍然指向一个有效的地址。但是,这导致了未定义的行为,因为内存管理器可以将该内存提供给其他代码块。

Calling free a second time can generate an error, because the memory manager doesn't know that pointer anymore as being valid (you just freed it!). In fact, this is undefined behaviour.

第二次调用free会产生错误,因为内存管理器不再知道该指针是有效的(您刚刚释放了它!)事实上,这是一种没有定义的行为。

#2


6  

Your program is being naughty and engaging in undefined behaviour.

你的程序是顽皮的和从事不明确的行为。

The memory is indeed returned to the system after the first free, it's just that freeing memory:

内存在第一次释放后确实被返回到系统中,它只是释放内存:

  1. doesn't necessarily clear it
  2. 并不清楚
  3. doesn't necessarily prevent you from accessing it
  4. 并不一定阻止你访问它

Freeing it again throws an error, as you've already released it back to the system.

再次释放它会抛出一个错误,因为您已经将它释放回系统。

This doesn't mean you can just malloc memory, free it again, and rely on still being able to access it later!

这并不意味着您可以仅仅malloc内存,释放它,并依赖于以后仍然能够访问它!

Firstly, the behaviour you are seeing is undefined - according to the C standard your program is not really valid. With your particular combination of compiler, operating system and environment you still have access to the contents of that memory after free, but it could just as easily break. Additionally, "undefined behaviour" allows compilers to get up to all sorts of shenanigans, making later code not do what you're expecting at all.

首先,您所看到的行为没有定义——根据C标准,您的程序不是真正有效的。使用编译器、操作系统和环境的特定组合,您仍然可以在免费后访问该内存的内容,但它也很容易被破坏。此外,“未定义的行为”允许编译器处理各种各样的诡计,使以后的代码完全不做您期望的事情。

Secondly, at any point after the free, the memory is available for subsequent mallocs. So even if you rely on the behaviour of your compiler/os/environment not breaking your use-after-free code, various other processes might fill that space with other stuff.

其次,在空闲后的任何时刻,内存都可以用于后续的mallocs。因此,即使您依赖于编译器/操作系统/环境的行为而不破坏您的“免用后”代码,各种其他进程也可能用其他东西填充这个空间。

Use-after-free is a pretty big nono, so just free it once, and never access freed memory.

use - afterfree是一个非常大的nono,所以只要释放它一次,并且永远不能访问被释放的内存。

See: https://cwe.mitre.org/data/definitions/416.html for the types of security problems you can run into.

参见:https://cwe.mitre.org/data/definitions/416.html用于您可能遇到的安全问题的类型。

#3


1  

The behaviour of your program is undefined.

程序的行为没有定义。

Once you call free, you should no longer attempt to read that memory. Note the behaviour on calling free again on the same pointer is also undefined: don't do it!

一旦你调用了free,你就不应该再试图读取那个内存。请注意,在同一个指针上再次调用free的行为也是未定义的:不要这样做!

There's no reason for the C runtime to be over-zealous and somehow disallow you explicitly from doing what you're doing as that would be suboptimal in well-written C programs.

没有理由让C运行时过于热情,并且不允许显式地不允许你做你正在做的事情,因为这在编写良好的C程序中是次优的。

#4


1  

Once you have called free(), you have indicated to memory manager that you are done with this memory. The memory manager can now use this memory to handle new allocation requests.

调用了free()之后,您已经向内存管理器表明您已经完成了这个内存。内存管理器现在可以使用该内存来处理新的分配请求。

If you are accessing the same memory again since you already have a pointer to the memory location, this is an undefined behavior.

如果您再次访问相同的内存,因为您已经有一个指向内存位置的指针,这是一个未定义的行为。

Calling free() again on the same memory location is also an undefined behavior.

在相同的内存位置上再次调用free()也是一种未定义的行为。

#1


9  

This is not odd, or wrong. When calling free on a pointer, you only tell the memory manager that it can re-use that portion of memory again for another malloc call. It won't erase the contents (this would take extra time with no function whatsoever). But, you can access it, because the pointer still points to a valid address. It leads to undefined behaviour though, because the memory manager could have given that memory to some other piece of code.

这不是奇怪的,也不是错误的。当在指针上调用free时,您只能告诉内存管理器,它可以再次为另一个malloc调用重用该内存部分。它不会删除内容(这需要额外的时间,没有任何函数)。但是,您可以访问它,因为指针仍然指向一个有效的地址。但是,这导致了未定义的行为,因为内存管理器可以将该内存提供给其他代码块。

Calling free a second time can generate an error, because the memory manager doesn't know that pointer anymore as being valid (you just freed it!). In fact, this is undefined behaviour.

第二次调用free会产生错误,因为内存管理器不再知道该指针是有效的(您刚刚释放了它!)事实上,这是一种没有定义的行为。

#2


6  

Your program is being naughty and engaging in undefined behaviour.

你的程序是顽皮的和从事不明确的行为。

The memory is indeed returned to the system after the first free, it's just that freeing memory:

内存在第一次释放后确实被返回到系统中,它只是释放内存:

  1. doesn't necessarily clear it
  2. 并不清楚
  3. doesn't necessarily prevent you from accessing it
  4. 并不一定阻止你访问它

Freeing it again throws an error, as you've already released it back to the system.

再次释放它会抛出一个错误,因为您已经将它释放回系统。

This doesn't mean you can just malloc memory, free it again, and rely on still being able to access it later!

这并不意味着您可以仅仅malloc内存,释放它,并依赖于以后仍然能够访问它!

Firstly, the behaviour you are seeing is undefined - according to the C standard your program is not really valid. With your particular combination of compiler, operating system and environment you still have access to the contents of that memory after free, but it could just as easily break. Additionally, "undefined behaviour" allows compilers to get up to all sorts of shenanigans, making later code not do what you're expecting at all.

首先,您所看到的行为没有定义——根据C标准,您的程序不是真正有效的。使用编译器、操作系统和环境的特定组合,您仍然可以在免费后访问该内存的内容,但它也很容易被破坏。此外,“未定义的行为”允许编译器处理各种各样的诡计,使以后的代码完全不做您期望的事情。

Secondly, at any point after the free, the memory is available for subsequent mallocs. So even if you rely on the behaviour of your compiler/os/environment not breaking your use-after-free code, various other processes might fill that space with other stuff.

其次,在空闲后的任何时刻,内存都可以用于后续的mallocs。因此,即使您依赖于编译器/操作系统/环境的行为而不破坏您的“免用后”代码,各种其他进程也可能用其他东西填充这个空间。

Use-after-free is a pretty big nono, so just free it once, and never access freed memory.

use - afterfree是一个非常大的nono,所以只要释放它一次,并且永远不能访问被释放的内存。

See: https://cwe.mitre.org/data/definitions/416.html for the types of security problems you can run into.

参见:https://cwe.mitre.org/data/definitions/416.html用于您可能遇到的安全问题的类型。

#3


1  

The behaviour of your program is undefined.

程序的行为没有定义。

Once you call free, you should no longer attempt to read that memory. Note the behaviour on calling free again on the same pointer is also undefined: don't do it!

一旦你调用了free,你就不应该再试图读取那个内存。请注意,在同一个指针上再次调用free的行为也是未定义的:不要这样做!

There's no reason for the C runtime to be over-zealous and somehow disallow you explicitly from doing what you're doing as that would be suboptimal in well-written C programs.

没有理由让C运行时过于热情,并且不允许显式地不允许你做你正在做的事情,因为这在编写良好的C程序中是次优的。

#4


1  

Once you have called free(), you have indicated to memory manager that you are done with this memory. The memory manager can now use this memory to handle new allocation requests.

调用了free()之后,您已经向内存管理器表明您已经完成了这个内存。内存管理器现在可以使用该内存来处理新的分配请求。

If you are accessing the same memory again since you already have a pointer to the memory location, this is an undefined behavior.

如果您再次访问相同的内存,因为您已经有一个指向内存位置的指针,这是一个未定义的行为。

Calling free() again on the same memory location is also an undefined behavior.

在相同的内存位置上再次调用free()也是一种未定义的行为。