我还可以对一个对其进行第二次malloc()调用的变量调用free()吗?

问题描述 投票:4回答:2

我想知道当一个系统如何释放内存时,malloc()调用是否与你分配malloc()的初始变量绑定在一起。

例如,我可以执行以下操作:

void * ptr1 = malloc(50);
void * ptr2 = ptr1;
ptr1 = malloc(25);
free(ptr2);

我打算释放最初分配给ptr1的内存,但后来用另一个指针释放它。

c memory malloc
2个回答
11
投票

让我们一步一步地介绍(UNDEF意味着我们不知道什么是值; valid意味着指针可以安全使用):

void *ptr1, *ptr2;    /* ptr1=UNDEF (invalid), ptr2=UNDEF (invalid) */
ptr1 = malloc(50);    /* ptr1=0xAAA (valid),   ptr2=UNDEF (invalid) */
ptr2 = ptr1;          /* ptr1=0xAAA (valid),   ptr2=0xAAA (valid)   */
ptr1 = malloc(25);    /* ptr1=0xBBB (valid),   ptr2=0xAAA (valid)   */
free(ptr2);           /* ptr1=0xBBB (valid),   ptr2=UNDEF (invalid) */

free()不知道它传递的指针存储在哪个变量中;不保证(但也不保证不)以任何方式更新变量或与变量交互。从应用程序开发人员的角度来看,有效改变的是,实际使用该指针是否安全,或者在返回它的malloc()调用期间分配给内存块的任何其他引用是否安全。

正如@M.M in comments所提到的,C语言规范是明确的,指向未释放对象的指针的值是未定义的,并允许编译器以任何方式修改它;请参阅Why does MISRA C state that a copy of pointers can cause a memory exception?进一步讨论。


2
投票

简短回答:是的

更长的回答:

你不是在“变量”上调用自由,而是在存储在变量中的值上调用。

为了更好地理解发生了什么,最好将内存视为一个大字节数组,并将指针可视化为该数组的数字索引。在您可能遇到的大多数架构上,这实际上是幕后发生的事情。

当你这样做

void * ptr1 = malloc(50);

malloc保留一个50字节的块并返回指向该块的指针。该指针只不过是一个数字索引,告诉我们内存中保留块的起始位置。

从理论上讲,我们可以(在某些架构上)编写

int ptr1 = (int)malloc(50);

我们没有这样做的原因是:

  1. sizeof(int)可能不够大,无法容纳指针
  2. void *告诉编译器存储在ptr1中的数值应该被视为内存地址。

如果我们继续查看您的代码:

void * ptr2 = ptr1;

这里没有什么神奇的事情发生。存储在ptr1中的“数值”被复制到ptr2中,就像ptr1ptr2是正常的整数变量一样。

ptr1 = malloc(25);

在这里,您使用新的“数值”覆盖ptr1的内容,但旧值仍然作为ptr2中的副本存在。

free(ptr2);

在这里,您可以使用存储在free中的值调用ptr2。这是malloc(50)返回的值。 free不关心哪个变量持有该值/地址。它只关心值/地址指向使用malloc保留的内存块的第一个字节。

理论上,如果你知道malloc(50)返回值0xb00b1e5就可以了

free((void *) 0xb00b1e5);

但是你无法安全地预测malloc会返回什么,所以不要这样做。

© www.soinside.com 2019 - 2024. All rights reserved.