5

这是我的程序:

#include <stdio.h>
#include <stdlib.h>

main(){
   char *p1, *p2, *p3, *p4;

   p1 = (char*)malloc(10);
   p2 = (char*)malloc(10);
   p3 = (char*)malloc(16);
   p4 = (char*)malloc(32);

   printf("p1 points at: %d\n", p1);
   printf("p2 points at: %d\n", p2);
   printf("p3 points at: %d\n", p3);
   printf("p4 points at: %d\n\n", p4);

   system("PAUSE");
}

这会在我的 PC 上产生以下输出:

p1 指向:6492080

p2 点在:6492104

p3 点在:6492128

p4 指向:6492152

因此,无论分配多少字节,malloc 分配的每个内存空间都从 24 个字节开始。这是为什么?我感谢您的帮助!

4

3 回答 3

5

的确切行为malloc取决于您的特定实现(编译器/libc/OS)。通过打印出地址,您的程序将从事未定义的行为。

如果您通过告诉我们您正在使用什么编译器、您在什么操作系统、什么架构以及您正在使用什么版本的 libc 来缩小您的问题的范围,那么我们可能能够就该实现给出更具体的答案,并且为什么数字是24。

我的猜测是,在您的实现中,每个malloced 内存区域都需要从一个 8 的倍数的地址开始,并且还有 8 个字节的开销。

编辑:如果您malloc在 p4 之后再次调用以创建 p5,则该模式肯定无法继续,因此您的声明“malloc 分配的每个内存空间进一步开始 24 个字节,无论分配了多少字节。” 是假的。

于 2012-10-20T15:20:12.033 回答
3

不能保证 anint和 some void*orchar*指针具有相同的大小(在我的 Debian/Linux/AMD64 系统上,int-s 是 32 位,但指针是 64 位)。您可能想要包含<stdint.h>并使用intptr_t.

的实现malloc有时可能会在分配的区域之前保留几个字节用于管理目的。并且malloc应该始终返回一个足够对齐的指针(对齐约束是编译器、运行时和处理器特定的)。绝对不能保证及时malloc返回越来越多的结果序列(尤其是在实际程序中,数百万次调用malloc与数百万次调用混合在一起free;您甚至可能在如此长时间运行的进程中出现一些内存碎片)。

而且我很确定,如果您在p5 = malloc(10120);之后添加 a ,您将看不到andp4之间的 24 字节距离,因为当它成功时保证其结果不是任何先前结果的别名,因此应该至少有一个距离32 字节(其中包含 32 字节块)。p5p4mallocp5p4

几乎总是,标准 C 库实现malloc了一些较低级别的原语,通常是一些系统调用来获取连续的虚拟内存页面。在Linux上,这些系统 调用通常是mmap (2) 可能与理解)。因此,您可以通过切换到 Linux 来了解更多信息。sbrk(2)mallocmalloc

malloc理论上可能的实现总是失败。在实践中,malloc可能会成功,但您应该始终测试失败的情况。

当然,如果可能的话,大多数实现都会在其实现中关心并重free用最近的free-d 内存区域(没有任何系统调用)malloc。如何组织堆以使其能够高效mallocfree高效是困难的(如果您希望它非常好,可能仍然是一个研究课题)。

您可能想阅读malloc上的维基百科页面。

于 2012-10-20T15:22:38.897 回答
1

malloc应为size大小对象分配空间。例如,没有什么可以阻止您的实现为对齐目的添加填充字节。另一个例子:一些内存管理实现在分配空间之前保持块的大小。

如果您想要更多细节,您应该精确您的实施。

于 2012-10-20T15:25:13.923 回答