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



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

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

由于我为 100 个整数分配了空间,因此我预计大小为 400。但输出是 409。对于 50 int,输出为 209,对于 1000 int,输出为 4009。有人可以解释为什么输出偏差 9 个字节吗?

假设实现是 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.

这解释了开销的存在。

现在,对于"关闭 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,所以你应该使用该类型来访问它。

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

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

malloc 实现还利用操作系统返回的分配的自然对齐,即将实际分配大小四舍五入为操作系统保证的对齐方式(这将考虑额外的 8 个字节),或者它还在分配结束时分配 4 个字节以用作保护值。

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

相关内容

  • 没有找到相关文章

最新更新