【发布时间】:2019-03-27 19:39:39
【问题描述】:
这个赋值要求我们使用malloc()(命名为var1和var2)分配两个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);
}
此代码导致以下输出:
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
如您所见,当我解除分配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
(为了清楚起见,我所做的只是从前面的代码中删除了free(var1),因此“AFTER DEALLOCATING var1”部分现在显示的堆地址与前面的集合完全相同,但它确实改变了var1 在第三部分。)
谁能告诉我这里发生了什么?我能想到的唯一合乎逻辑的解释是,当我使用free() 释放var1 然后打印地址时,它只是打印它指向的最后一个地址,然后当我为var1 第二次,它只是用var1 的新值“回填”之前的地址。这有意义吗?我的代码中是否有错误,或者这正是 C 在为变量释放内存然后重新分配它时的行为方式?
【问题讨论】:
-
1.
free()接受一个指针,您可以提供一个变量。但是,它不会更改该变量的内容。 (指针由指向free()的值给出。) 2. 如果你free()N 字节和稍后(而是立即)malloc()N 字节再次,你为什么不应该得到相同的地址?听起来,堆管理做得很好——它重新使用了足够大小的可用空间。 ;-) -
malloc实现为相同大小的新对象重用空间是非常有意义的。 -
你好。不是您要的,但您不再需要cast the return value of malloc。另外,我发现使用
int *var = malloc(sizeof *var)而不是int *var = malloc(sizeof(int))很有用。这样我就可以更改var的类型,而不会忘记在 malloc 调用中更改它(例如float *var = malloc(sizeof(int)))。 -
你基本上是对的。这里的教训是,即使在释放内存之后,您可能仍然有指向该内存的变量,尽管您不拥有它。这些“悬空指针”会导致很多痛苦,这就是为什么清除此类指针被认为是一种好的做法,例如
free(p);p=NULL;
标签: c malloc heap-memory free memory-address