首页 文章

为什么malloc(1)用于存储4字节整数?

提问于
浏览
1

根据我的理解,malloc(x)返回一个x字节长的内存块 .

所以要存储一个4字节的整数,我会这样做:

int *p = (int *)malloc(4);
    *p = 100;

因为sizeof(int)为我返回4 .

但是,如果我这样做:

int *p = (int *)malloc(1);
    *p = 100;

它似乎工作完全相同,没有存储值的问题 .

为什么malloc()请求的内存量似乎不重要? 4字节整数不应该需要malloc(4)吗?

6 回答

  • 4

    如果这适用于您的情况,它只是偶然工作,并不保证工作 . 这是未定义的行为(比较this SO question),一切都可能发生 .

    你期望发生什么?你的程序崩溃了?

    如果你经常调用 mallocfree ,这可能仍然会发生 . malloc 经常比请求多占用一些字节,并使用额外的空间进行管理(所有内存块的链表,内存块的大小) . 如果你在分配的块之前或之后写了一些字节,那么你很可能会混淆内部管理结构,而后续的 free 会崩溃 .

    如果malloc内部总是分配最少n个字节,那么如果访问字节n 1,程序可能只会崩溃 . 此外,操作系统通常只能根据页面保护内存 . 如果一个页面的大小为512字节,并且您的malloc-ed字节位于页面中间,那么您的进程可能能够读写页面的其余部分,并且只会在访问下一个内存页面时崩溃 . 但要记住:即使这有效,也是未定义的行为 .

  • 2

    C编程语言使您能够用脚射击自己 .

    它故意给程序员带来负担,他们应该知道他们在做什么 . 从广义上讲,原因是要实现性能,可读性和可移植性 .

    代码的行为未定义 . 如果要求1个字节,则期望只返回一个可用字节 . 事实上,操作系统和C运行时库似乎给你的回馈多一点,这只不过是一种奇怪的特性 .

    在其他情况下,编译器可能只是吃你的猫 .

    最后,在 malloc 的调用中使用 sizeof 而不是硬编码 int 类型的大小:在许多系统上 sizeof(int) 是2,4是常见的,并且标准允许所有大于1的值 . 在您的情况下,可以使用 sizeof(int)sizeof(*p) . 有些人喜欢后者,因为那时你并没有在 sizeof 调用中硬编码变量的类型,所以要防止可能的变量类型更改 . (注意 sizeof(*p) 是编译时可评估的并且使用静态类型信息;因此如果你理解了它,它可以在 p 本身"exists"之前使用 . )

  • 0

    它似乎工作完全相同,没有存储值的问题 .

    您使用代码调用未定义的行为,因此您无法确定它是否有效 . 为了为整数分配内存,你应该这样做:

    int *p;
    p = malloc(sizeof (*p) ); //you can use sizeof(*p) as p is already declared and here you use the size of its content, which is actually the size of an int
    if (p != NULL)
        *p = 100;
    
  • 0

    通常 malloc 的实现方式是它分配的内存大小不小于段落大小等于16个字节 . 所以当你需要例如4字节的内存时 malloc 实际上分配了16个字节 . 但是,此行为未在C标准中描述,您可能不会依赖它 . 因此,这意味着您显示的程序具有未定义的行为 .

  • 2

    我认为这是因为填充,即使你正在调用 malloc(1) 填充字节随内存一起提供 . 请检查此链接http://www.delorie.com/gnu/docs/glibc/libc_31.html

  • 0

    malloc ,因为来自C运行时或OS内核的所有内存块分配函数都针对内存访问和对象对齐进行了优化 .

    而且, malloc 具体地说,在分配的空间前分配一个隐藏的控制块来跟踪分配(所需的空间, space allocated 等) .

    malloc must also to guarantee that the allocated memory address is suitably aligned for any storage object ,这意味着该块将以8,16,32或甚至64或128字节的边界开始,具体取决于处理器,一般来自硬件(即一些特殊的MMU) . 边界也取决于访问速度,某些处理器具有不同的行为,具有不同的存储器访问(1,2,4,8,...字节)和地址边界 . 此约束驱动 malloc 代码规范和分配器逻辑内存块分区 .

    在实际的一面让我们考虑一个X86处理器的分配器,它通常会返回一个在8字节边界(32位代码)上对齐的块,这对于int,float和even double都很有用 . 为此, malloc 将'blocks'中可用的内存区域划分为最小分配空间 . 当您分配甚至1个字节时,该函数至少分配一个块 . 最终,这个块可以承载一个整数,甚至是一个双精度 but it is implementation dependent, and you can't consider it deterministic ,因为在同一函数的未来版本中,行为可以改变 .

    现在,我希望,这很清楚,因为你的代码似乎有效,请记住 this is Undefined-Behavior and you must keep it for that . IT现在可以工作,而不是下一次修订,它可以在某些硬件上崩溃而在另一台处理器或机器上崩溃 .

相关问题