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

时间:2018-10-23 14:11:55

标签: c malloc heap-memory free 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); 

}

此代码产生以下输出:

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为变量分配内存然后重新分配内存时的行为方式吗?

3 个答案:

答案 0 :(得分:11)

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

如果更改malloc调用以请求与原始分配不同的大小,则您可能会获得不同的地址,因为旧的malloc准备的块可能不足以满足新的请求。但是它们可能就足够了,因此地址可能不会更改。

偶然地:

  • void main()不正确。应该是int main(void)
  • C标准不支持在其指向的空间被释放之后打印地址。它“起作用”的情况并不少见,但这是不合适的。 C 2018 6.2.4 2告诉我们“指针所指向的对象(或刚刚过去的对象)达到其生命周期的尽头时,指针的值将变得不确定。”当用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()之后保持不变。但是您不能再访问该地址。

当他们再次分配变量时,获得相同的地址并不奇怪,因为在该地址上应该有一个适当大小的可用段。但是,您不能保证获得相同的地址-库代码会处理从可用地址中最佳选择的地址。

相关问题