2

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

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

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

4

2 回答 2

6

假设实现是 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,因此您应该使用该类型来访问它。

于 2012-08-15T20:21:38.310 回答
0

如果该值是分配大小,除了它依赖于实现之外,我会冒险猜测并说您有一些额外的可能性9

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

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

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

于 2012-08-15T20:43:22.557 回答