Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/62.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C free()如何影响堆上的内存地址?_C_Malloc_Heap Memory_Free_Memory Address - Fatal编程技术网

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

C free()如何影响堆上的内存地址?,c,malloc,heap-memory,free,memory-address,C,Malloc,Heap Memory,Free,Memory Address,此赋值要求我们使用malloc()(名为var1和var2)分配两个int类型变量,打印每个变量的地址(堆栈上指针的地址和堆上的地址),然后使用free()取消分配var1,再次打印地址,然后在堆中为var1分配另一个空间,并第三次打印地址。我相信讲师试图告诉我们var1的堆地址应该改变,但它总是保持不变。。。除非我从代码中删除free(var1)。讲师做了一个类似的演示,但没有使用free()来释放任何变量,因此我们从未看到这是如何工作的 这是我的密码: #include <stdio.

此赋值要求我们使用
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); 

}
如您所见,当我解除分配
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)
,因此“释放var1后”部分现在显示与前面的集合完全相同的堆地址,但它确实在第三部分中更改了var1的堆地址。)

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

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

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

标准上说:

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


一个常见的错误是使用测试
if(ptr==NULL)
检查是否已正确释放指针。这将不起作用。

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

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

顺便说一下:

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

在第一个示例中,用于指向堆的指针的位置值在
free()之后在堆栈中保持不变。但是你不能再访问那个地址了


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

一,
free()
获取可能随变量提供的指针。但是,它不会更改该变量的内容。(指针由值指定给
free()
)2。如果您
free()
N个字节,然后又是
malloc()
N个字节,为什么不应该得到相同的地址?听起来,堆管理做得很好——它重新使用了足够大的可用空间对于
malloc
实现来说,为相同大小的新对象重用空间是非常有意义的。不是你要求的,但你不需要再这样做了。另外,我发现使用
int*var=malloc(sizeof*var)
而不是
int*var=malloc(sizeof(int))
很有用。这样我就可以更改
var
的类型,而不会忘记在malloc调用中更改它(例如
float*var=malloc(sizeof(int))
。你基本上是对的。这里的教训是,即使在释放内存之后,您仍然可能有指向该内存的变量,尽管您并不拥有它。这些“悬而未决的指针”会造成很多痛苦,这就是为什么清除这些指针被认为是好的做法,例如
free(p);p=零C标准不保证“释放指针不会影响指针的内容”。指针传递到
free
后,使用其值有未指定的行为。@EricPostChil但是
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