free() 如何影响堆上的内存地址?
How does free() affect the memory address on the heap?
这个赋值要求我们使用malloc()
分配两个int类型的变量(命名为var1
和var2
),打印每个变量的地址(指针的地址堆栈和堆上的地址),然后使用 free()
释放 var1
,再次打印地址,然后在堆中为 var1
分配另一个 space 并打印第三次发言。我相信讲师试图向我们展示 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
分配内存 space 时,它也没有改变。但是,如果我简单地从程序中删除 free(var1)
行,它只是为 var1
分配第二个内存 space 并指向堆上的内存,它具有不同的内存地址:
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
然后打印地址时,它只是打印它指向的最后一个地址,然后当我' m 第二次为var1
分配内存,它只是"backfilling" 以前的地址加上var1
的新值。这有意义吗?我的代码中是否有错误,或者这就是 C 在为变量释放内存然后重新分配时的行为方式?
The only logical explanation I can come up with is that when I'm using free() to deallocate var1 and then printing the address, it's simply printing the LAST address that it pointed to
有点对。释放指针根本不会影响指针的内容。或者更准确地说,它的价值在被释放后是不确定的。事实上,根据标准,您甚至不能相信指针包含它在调用 free
之前所做的地址。据我所知,在大多数情况下它会,但你不能相信它。
标准说:
C 2018 6.2.4 2: “The value of a pointer becomes indeterminate when the object it points to (or just past) reaches the end of its lifetime.”
一个常见的错误是使用测试 if(ptr == NULL)
来检查您是否已正确释放指针。这行不通。
当内存被释放然后重新分配时,malloc
可能 return 相同的地址是完全正常的。 return 不同的地址也是正常的。
如果您更改 malloc
调用以请求与原始分配不同的大小,您可能会得到不同的地址,因为 malloc
准备的旧块可能不足以满足新请求。但它们可能就足够了,所以地址可能不会改变。
顺便说一句:
void main()
不正确。应该是 int main(void)
.
- C 标准不支持在它指向的 space 被释放后打印地址。它“起作用”并不少见,但这是不合适的。 C 2018 6.2.4 2 告诉我们“当指针指向(或刚刚过去)的对象达到其生命周期结束时,指针的值变得不确定。”当用
malloc
分配的对象用 free
释放时,它的生命周期结束。
在第一个例子中,在free()
之后,用于指向堆的指针的值在堆栈中保持不变。但您无法再访问该地址。
当他们再次分配变量时,您得到相同的地址并不奇怪,因为该地址应该有一个大小合适的可用段。但是,您不能保证获得相同的地址 - 哪个地址是可用地址的最佳选择由库代码处理。
这个赋值要求我们使用malloc()
分配两个int类型的变量(命名为var1
和var2
),打印每个变量的地址(指针的地址堆栈和堆上的地址),然后使用 free()
释放 var1
,再次打印地址,然后在堆中为 var1
分配另一个 space 并打印第三次发言。我相信讲师试图向我们展示 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
分配内存 space 时,它也没有改变。但是,如果我简单地从程序中删除 free(var1)
行,它只是为 var1
分配第二个内存 space 并指向堆上的内存,它具有不同的内存地址:
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
然后打印地址时,它只是打印它指向的最后一个地址,然后当我' m 第二次为var1
分配内存,它只是"backfilling" 以前的地址加上var1
的新值。这有意义吗?我的代码中是否有错误,或者这就是 C 在为变量释放内存然后重新分配时的行为方式?
The only logical explanation I can come up with is that when I'm using free() to deallocate var1 and then printing the address, it's simply printing the LAST address that it pointed to
有点对。释放指针根本不会影响指针的内容。或者更准确地说,它的价值在被释放后是不确定的。事实上,根据标准,您甚至不能相信指针包含它在调用 free
之前所做的地址。据我所知,在大多数情况下它会,但你不能相信它。
标准说:
C 2018 6.2.4 2: “The value of a pointer becomes indeterminate when the object it points to (or just past) reaches the end of its lifetime.”
一个常见的错误是使用测试 if(ptr == NULL)
来检查您是否已正确释放指针。这行不通。
当内存被释放然后重新分配时,malloc
可能 return 相同的地址是完全正常的。 return 不同的地址也是正常的。
如果您更改 malloc
调用以请求与原始分配不同的大小,您可能会得到不同的地址,因为 malloc
准备的旧块可能不足以满足新请求。但它们可能就足够了,所以地址可能不会改变。
顺便说一句:
void main()
不正确。应该是int main(void)
.- C 标准不支持在它指向的 space 被释放后打印地址。它“起作用”并不少见,但这是不合适的。 C 2018 6.2.4 2 告诉我们“当指针指向(或刚刚过去)的对象达到其生命周期结束时,指针的值变得不确定。”当用
malloc
分配的对象用free
释放时,它的生命周期结束。
在第一个例子中,在free()
之后,用于指向堆的指针的值在堆栈中保持不变。但您无法再访问该地址。
当他们再次分配变量时,您得到相同的地址并不奇怪,因为该地址应该有一个大小合适的可用段。但是,您不能保证获得相同的地址 - 哪个地址是可用地址的最佳选择由库代码处理。