我试图了解如何使用 malloc 在堆上分配内存,并发现了以下观察结果,但无法理解其背后的原因。如果有人能解释一下就太好了。
首先我们看一下我写的代码:
#include<stdio.h>
#include<stdlib.h>
void print_int_heap(unsigned int *ptr, int len)
{
printf("PREV_SIZE: [%08x] SIZE: [%08x] MEM: [%08x] for INT malloc(%d)\n", *(ptr-2), *(ptr-1), ptr, len);
}
void print_char_heap(char *ptr, int len)
{
printf("PREV_SIZE: [%08x] SIZE: [%08x] MEM: [%08x] for CHAR malloc(%d)\n", *(ptr-2), *(ptr-1), ptr, len);
}
int main() {
unsigned int *ptr1 = malloc(20);
print_int_heap(ptr1, 20);
char *ptr2 = malloc(20)
print_char_heap(ptr2, 20);
return 0;
}
我从上述程序得到的输出是:
PREV_SIZE: [0x00000000] SIZE: [0x00000019] MEM: [0x0804b008] for INT malloc(20)
PREV_SIZE: [0x00000000] SIZE: [0x00000000] MEM: [0x0804b020] for INT malloc(20)
我可以理解 int malloc 的输出,但我不明白为什么 char malloc 的 block 大小值为 0?
最佳答案
如果 ptr
是 int*
,则 *(ptr - 1)
指的是 sizeof(int)
>ptr 引用之前的字节。这通常是一个 32 位数量,从 ptr
之前的四个字节开始。
同样,如果它是 char*
,则 *(ptr - 1)
指的是之前的 sizeof(char)
字节ptr
引用。 sizeof(char)
始终为 1;通常这将是 ptr
值之前的单个字节中的 8 位数量。
这些显然是完全不同的事情。
顺便说一下,你可以写ptr[-1]
。但正如上面的分析所示,这确实不是您想要的。您希望将 ptr
转换为指向您认为位于 ptr
之前的对象的数据类型的指针,可能是 uint32_t
。
从技术上讲,这都是未定义的行为,但是如果您的 malloc
实现在分配之前存储数据并且您知道该数据的类型,那么我会说读取它就可以了。 (虽然盯着系统函数的内部数据总是有点不礼貌。)
请注意,并非所有 malloc
实现都执行相同的操作。您很可能会找到一个在其他地方存储长度或根本不存储长度的文件。
关于c - 了解堆中的内存分配,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52286552/