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

时间:2022-04-02 03:59:52

This assignment asks us to allocate two int-type variables using malloc() (named var1 and var2), print the addresses of each variable (the address of the pointer on the stack and the address on the heap), then use free() to deallocate var1, print the addresses again, then allocate another space in the heap for var1 and print the addresses a third time. I believe that the instructor is trying to show us that the heap address for var1 is supposed to change, but it always stays the same... unless I remove free(var1) from the code. The instructor did a similar demonstration, but did not use free() to deallocate any variables, so we never saw how this was supposed to work.

这个赋值要求我们使用malloc()(名为var1和var2)分配两个int类型变量,打印每个变量的地址(堆栈上指针的地址和堆上的地址),然后使用free()要取消分配var1,再次打印地址,然后在堆中为var1分配另一个空间并第三次打印地址。我相信教师试图告诉我们var1的堆地址应该改变,但它总是保持不变......除非我从代码中删除free(var1)。教师做了类似的演示,但是没有使用free()来释放任何变量,所以我们从未看到过它应该如何工作。

Here is my code:

这是我的代码:

#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); 

}

This code results in this output:

此代码导致此输出:

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

As you can see, the heap address does not change for var1 when I deallocate it, and it doesn't change when I allocate memory space for var1 again. However, if I simply remove the free(var1) line from the program, it simply assigns a second memory space for var1 and points to that on the heap, which DOES have a different memory address:

正如您所看到的,当我释放它时,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

(Just to be clear, all I did was remove free(var1) from the previous code, so the "AFTER DEALLOCATING var1" section now shows the exact same heap address as the previous set, but it DOES change the heap address of var1 in the third section.)

(为了清楚起见,我所做的就是从前面的代码中删除free(var1),所以“AFTER DEALLOCATING var1”部分现在显示与前一个集合完全相同的堆地址,但它确实改变了var1的堆地址第三部分。)

Can anybody tell me what is happening here? 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, and then when I'm allocating memory for var1 the second time, it's simply "backfilling" the previous address with the new value of var1. Does this make sense? Do I have errors in my code, or is this just how C behaves when deallocating memory for a variable and then reallocating it?

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

3 个解决方案

#1


9  

It is perfectly normal that malloc might return the same addresses when memory is freed and then reallocated. It would also be normal for it to return different addresses.

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

If you change the malloc calls to request different sizes than the original allocations, you might get different addresses, since the old blocks malloc had prepared might not be enough for the new requests. But they might be enough, so the addresses might not change.

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

Incidentally:

  • void main() is incorrect. It should be int main(void).
  • void main()不正确。它应该是int main(void)。

  • Printing an address after the space it points to has been freed is not supported by the C standard. It is not uncommon for it to “work,” but it is not proper. C 2018 6.2.4 2 tells us “The value of a pointer becomes indeterminate when the object it points to (or just past) reaches the end of its lifetime.” When an object allocated with malloc is freed with free, its lifetime ends.
  • C标准不支持在其指向的空间被释放后打印地址。它“工作”并不罕见,但它并不恰当。 C 2018 6.2.4 2告诉我们“当指针指向(或刚刚过去)的对象到达其生命周期结束时,指针的值变得不确定。”当使用malloc分配的对象被释放时,其生命周期结束。

#2


4  

In the first example, the value of where the pointer used to point at the heap remains untouched at the stack after free(). But you can no longer access that address.

在第一个示例中,指向堆的指针的值在free()之后在堆栈处保持不变。但您无法再访问该地址。

When they allocate the variable yet again, it is not strange that you get the same address, as there should be an available segment of the right size at that address. You are however not guaranteed to get the same one - which address that's the best pick from what's available is handled by the library code.

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

#3


3  

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()来释放var1然后打印地址时,它只是打印它所指向的最后一个地址。

Kind of right. Freeing a pointer does not affect the content of the pointer at all. Or to be more precise, it's value is indeterminate after being freed. In fact, according to the standard you cannot even trust the pointer to contain the address it did before invoking free. As far as I know, it will in most cases, but you cannot trust it.

没错。释放指针根本不会影响指针的内容。或者更确切地说,它被释放后的价值是不确定的。事实上,根据标准,你甚至不能信任指针包含它在调用free之前所做的地址。据我所知,在大多数情况下,它会让你无法信任。

The standard says:

标准说:

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.”

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

A common mistake is to use the test if(ptr == NULL) as a check if you have properly freed the pointer. This will not work.

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

#1


9  

It is perfectly normal that malloc might return the same addresses when memory is freed and then reallocated. It would also be normal for it to return different addresses.

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

If you change the malloc calls to request different sizes than the original allocations, you might get different addresses, since the old blocks malloc had prepared might not be enough for the new requests. But they might be enough, so the addresses might not change.

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

Incidentally:

  • void main() is incorrect. It should be int main(void).
  • void main()不正确。它应该是int main(void)。

  • Printing an address after the space it points to has been freed is not supported by the C standard. It is not uncommon for it to “work,” but it is not proper. C 2018 6.2.4 2 tells us “The value of a pointer becomes indeterminate when the object it points to (or just past) reaches the end of its lifetime.” When an object allocated with malloc is freed with free, its lifetime ends.
  • C标准不支持在其指向的空间被释放后打印地址。它“工作”并不罕见,但它并不恰当。 C 2018 6.2.4 2告诉我们“当指针指向(或刚刚过去)的对象到达其生命周期结束时,指针的值变得不确定。”当使用malloc分配的对象被释放时,其生命周期结束。

#2


4  

In the first example, the value of where the pointer used to point at the heap remains untouched at the stack after free(). But you can no longer access that address.

在第一个示例中,指向堆的指针的值在free()之后在堆栈处保持不变。但您无法再访问该地址。

When they allocate the variable yet again, it is not strange that you get the same address, as there should be an available segment of the right size at that address. You are however not guaranteed to get the same one - which address that's the best pick from what's available is handled by the library code.

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

#3


3  

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()来释放var1然后打印地址时,它只是打印它所指向的最后一个地址。

Kind of right. Freeing a pointer does not affect the content of the pointer at all. Or to be more precise, it's value is indeterminate after being freed. In fact, according to the standard you cannot even trust the pointer to contain the address it did before invoking free. As far as I know, it will in most cases, but you cannot trust it.

没错。释放指针根本不会影响指针的内容。或者更确切地说,它被释放后的价值是不确定的。事实上,根据标准,你甚至不能信任指针包含它在调用free之前所做的地址。据我所知,在大多数情况下,它会让你无法信任。

The standard says:

标准说:

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.”

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

A common mistake is to use the test if(ptr == NULL) as a check if you have properly freed the pointer. This will not work.

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