free()如何影响堆上的内存地址?

Dus*_* R. 14 c malloc free heap-memory memory-address

这个赋值要求我们使用malloc()(命名var1var2)分配两个int类型变量,打印每个变量的地址(堆栈上指针的地址和堆上的地址),然后free()用来解除分配var1,再次打印地址,然后在堆中分配另一个空间var1并第三次打印地址.我相信教师试图告诉我们堆地址var1应该改变,但它始终保持不变......除非我free(var1)从代码中删除.教练做了类似的演示,但没有free()用来解除分配任何变量,所以我们从来没有看到它应该如何工作.

这是我的代码:

#include <stdio.h>
#include <stdlib.h>

void main()
{

int *var1 = (int*)malloc(sizeof(int)); 
*var1 = 1000;                   
int *var2 = (int*)malloc(sizeof(int)); 
*var2 = 2000;

printf("Addresses of var1\n");
printf("Pointer on stack: %p / Heap: %p\n\n", &var1, var1); 
printf("Addresses of var2\n");
printf("Pointer on stack: %p / Heap: %p\n\n", &var2, var2);

free(var1);

printf("AFTER DEALLOCATING var1 FROM THE HEAP\n");
printf("Addresses of var1\n");
printf("Pointer on stack: %p / Heap: %p\n\n", &var1, var1); 
printf("Addresses of var2\n");
printf("Pointer on stack: %p / Heap: %p\n\n", &var2, var2);

var1 = (int*) malloc(sizeof(int));
*var1 = 1500;

printf("NEW MEMORY ADDRESS ALLOCATED FOR var1\n");
printf("Addresses of var1\n");
printf("Pointer on stack: %p / Heap: %p\n\n", &var1, var1); 
printf("Addresses of var2\n");
printf("Pointer on stack: %p / Heap: %p\n\n", &var2, var2); 

}
Run Code Online (Sandbox Code Playgroud)

此代码导致此输出:

Addresses of var1
Pointer on stack: 0xffffcbf8 / Heap: 0x600000390

Addresses of var2
Pointer on stack: 0xffffcbf0 / Heap: 0x6000003b0

AFTER DEALLOCATING var1 FROM THE HEAP
Addresses of var1
Pointer on stack: 0xffffcbf8 / Heap: 0x600000390

Addresses of var2
Pointer on stack: 0xffffcbf0 / Heap: 0x6000003b0

NEW MEMORY ADDRESS ALLOCATED FOR var1
Addresses of var1
Pointer on stack: 0xffffcbf8 / Heap: 0x600000390

Addresses of var2
Pointer on stack: 0xffffcbf0 / Heap: 0x6000003b0
Run Code Online (Sandbox Code Playgroud)

正如您所看到的,堆地址var1在我解除分配时不会改变,并且当我var1再次分配内存空间时它不会改变.但是,如果我只是free(var1)从程序中删除该行,它只是为var1堆分配第二个内存空间并指向堆上的内存空间,它具有不同的内存地址:

Addresses of var1 
Pointer on stack: 0xffffcbf8 / Heap: 0x600000390

Addresses of var2
Pointer on stack: 0xffffcbf0 / Heap: 0x6000003b0

AFTER DEALLOCATING var1 FROM THE HEAP
Addresses of var1
Pointer on stack: 0xffffcbf8 / Heap: 0x600000390

Addresses of var2
Pointer on stack: 0xffffcbf0 / Heap: 0x6000003b0

NEW MEMORY ADDRESS ALLOCATED FOR var1
Addresses of var1
Pointer on stack: 0xffffcbf8 / Heap: 0x600000420

Addresses of var2
Pointer on stack: 0xffffcbf0 / Heap: 0x6000003b0
Run Code Online (Sandbox Code Playgroud)

(为了清楚起见,我所做的只是free(var1)从前面的代码中删除,因此"AFTER DEALLOCATING var1"部分现在显示与前一个集合完全相同的堆地址,但它在第三部分中更改了var1的堆地址. )

谁能告诉我这里发生了什么?我能想到的唯一合乎逻辑的解释是,当我free()用来解除分配var1然后打印地址时,它只是打印它所指向的最后一个地址,然后当我var1第二次分配内存时,它只是使用新值"回填"上一个地址var1.这有意义吗?我的代码中是否有错误,或者这是在为变量释放内存然后重新分配它时C的行为方式?

Eri*_*hil 11

malloc在释放内存然后重新分配内存时,可能会返回相同的地址,这是完全正常的.它返回不同的地址也是正常的.

如果malloc将请求更改为请求与原始分配不同的大小,则可能会获得不同的地址,因为旧块malloc已准备好可能不足以满足新请求.但它们可能就够了,所以地址可能不会改变.

偶然:

  • void main()是不正确的.它应该是int main(void).
  • C标准不支持在其指向的空间被释放后打印地址.它"工作"并不罕见,但它并不恰当.C 2018 6.2.4 2告诉我们"当指针指向(或刚刚过去)的对象到达其生命周期结束时,指针的值变得不确定."当分配的对象malloc被释放时free,其生命周期结束.


klu*_*utt 5

我能想到的唯一合乎逻辑的解释是,当我使用 free() 解除分配 var1 然后打印地址时,它只是打印它指向的最后一个地址

有点对。释放指针根本不会影响指针的内容。或者更准确地说,它被释放后的价值是不确定的。事实上,根据标准,您甚至不能相信指针包含它在调用之前所做的地址free。据我所知,在大多数情况下它会,但你不能相信它。

标准说:

C 2018 6.2.4 2:“当指针指向(或刚刚过去)的对象到达其生命周期结束时,指针的值变得不确定。”

一个常见的错误是使用测试if(ptr == NULL)来检查您是否正确释放了指针。这是行不通的。

  • C 标准不保证“释放指针完全不会影响指针的内容”。将指针传递给 `free` 后,使用其值具有未指定的行为。 (3认同)