此分配要求我们使用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
然后打印地址时,它只是打印它指向的LAST地址,然后当我m第二次为var1
分配内存,只是用var1
的新值“回填”了先前的地址。这有意义吗?我的代码中是否有错误,或者这是C为变量分配内存然后重新分配内存时的行为方式吗?
答案 0 :(得分:11)
释放内存然后重新分配内存时,malloc
可能返回相同的地址是完全正常的。返回不同的地址也是正常的。
如果更改malloc
调用以请求与原始分配不同的大小,则您可能会获得不同的地址,因为旧的malloc
准备的块可能不足以满足新的请求。但是它们可能就足够了,因此地址可能不会更改。
偶然地:
void main()
不正确。应该是int main(void)
。malloc
分配的对象被{{ 1}},其生命周期结束。答案 1 :(得分:4)
我能想到的唯一合理的解释是,当我使用free()释放var1然后打印地址时,它只是打印它指向的LAST地址
正确的种类。释放指针完全不影响指针的内容。或者更确切地说,释放后它的值是不确定的。实际上,根据标准,您甚至不能信任指针包含它在调用if(ptr == NULL)
之前所做的地址。据我所知,它在大多数情况下都可以,但是您不能信任它。
标准说:
C 2018 6.2.4 2:“当指针指向(或刚刚过去)的对象达到其生命周期的尽头时,指针的值将变得不确定。”
一个常见的错误是使用测试/* CSS talk bubble */
h4:empty {
display: none;
}
.talk-bubble {
margin-top: 220px;
left: 390px;
display: inline-block;
position: absolute;
width: 200px;
height: auto;
background-color: purple;
}
.round{
border-radius: 10px;
}
.tri-right.right-in h4:before {
content: '';
position: absolute;
width: 0;
height: 0;
left: auto;
right: -20px;
top: 38px;
bottom: auto;
border: 12px solid;
border-color: purple transparent transparent purple;
}
/* talk bubble contents */
.talktext{
padding: 10px;
text-align: center;
line-height: 1.5em;
}
.talktext p{
/* remove webkit p margins */
-webkit-margin-before: 0em;
-webkit-margin-after: 0em;
}
/* end of talk bubble stuff */
作为检查是否正确释放了指针。这是行不通的。
答案 2 :(得分:4)
在第一个示例中,指针指向堆的位置的值在free()
之后保持不变。但是您不能再访问该地址。
当他们再次分配变量时,获得相同的地址并不奇怪,因为在该地址上应该有一个适当大小的可用段。但是,您不能保证获得相同的地址-库代码会处理从可用地址中最佳选择的地址。