c - 了解堆中的内存分配

标签 c memory-management heap-memory

我试图了解如何使用 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?

最佳答案

如果 ptrint*,则 *(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/

相关文章:

c - 当我知道重叠的一面时,memmove() 的替代方案是什么?

c - C 中的分配错误(函数或代码)和奇怪的行为

java - Android 中的内存管理

ios - UINavigationController 替代品

java - 如何在没有引用的情况下访问 Java 堆对象?

Android 内存管理——我的应用是否健康?

c函数反转字符串

c - linux 覆盖正在运行的二进制文件

c++ - 为结构(或类)行为数组赋值

c - OpenCl 中的结构具有大量内存地址