由C语言中的malloc分配的意外输出大小

时间:2012-08-15 20:04:50

标签: c memory-management malloc heap free

我已经读过malloc实际上分配了(required_size + 1)个内存块,它将大小存储在第一个块中,并返回指向第二个块的指针。这样free()知道要释放多少内存。所以,我写了一个小代码来输出这个大小。

int *p = (int *)malloc(100*sizeof(int));
printf("size = %d\n",p[-1]);

由于我正在为100个整数分配空间,我希望大小为400.但输出为409.对于50个int的输出为209而对于1000 int的输出为4009.有人可以解释为什么输出关闭按9个字节?

2 个答案:

答案 0 :(得分:5)

假设实现是glibc(或类似),可以在malloc.c的注释中找到以下内容:

Minimum overhead per allocated chunk:   4 or 8 bytes
   Each malloced chunk has a hidden word of overhead holding size
   and status information.

Minimum allocated size: 4-byte ptrs:  16 bytes    (including 4 overhead)
          8-byte ptrs:  24/32 bytes (including, 4/8 overhead)

   When a chunk is freed, 12 (for 4byte ptrs) or 20 (for 8 byte
   ptrs but 4 byte size) or 24 (for 8/8) additional bytes are
   needed; 4 (8) for a trailing size field and 8 (16) bytes for
   free list pointers. Thus, the minimum allocatable size is
   16/24/32 bytes.

这解释了开销的存在。

现在,对于'off by 1',标志对此负责。由于malloc()分配的大小(实际)总是8的倍数,因此三个最低有效位用于存储标志:

/* size field is or'ed with PREV_INUSE when previous adjacent chunk in use */
#define PREV_INUSE 0x1

/* extract inuse bit of previous chunk */
#define prev_inuse(p)       ((p)->size & PREV_INUSE)


/* size field is or'ed with IS_MMAPPED if the chunk was obtained with mmap() */
#define IS_MMAPPED 0x2

/* check for mmap()'ed chunk */
#define chunk_is_mmapped(p) ((p)->size & IS_MMAPPED)


/* size field is or'ed with NON_MAIN_ARENA if the chunk was obtained
   from a non-main arena.  This is only set immediately before handing
   the chunk to the user, if necessary.  */
#define NON_MAIN_ARENA 0x4

/* check for chunk from non-main arena */
#define chunk_non_main_arena(p) ((p)->size & NON_MAIN_ARENA)

编辑:啊,我差点忘了。大小存储为size_t,而不是int,因此您应该使用该类型来访问它。

答案 1 :(得分:0)

如果该值是分配大小,除了依赖于实现之外,我会冒险猜测并且说你有额外9的几种可能性。

对于不同意分配,这个数字可能总是很奇怪。鉴于大多数操作系统都具有以高于1字节的粒度返回的内置内存分配函数,malloc的实现可能使用分配大小的第一位来跟踪分配是否已被释放。

malloc实现也要么利用操作系统返回的分配的自然对齐,也就是将实际分配大小四舍五入到操作系统保证的对齐(这将占额外的8个字节) ,它还在分配结束时分配4个字节用作保护值。

但是,您可以从正在使用的平台和编译器的文档中了解有关存储分配信息的位置的更多信息。