2

malloc が実際に (required_size + 1) ブロックのメモリを割り当て、最初のブロックにサイズを格納し、2 番目のブロックへのポインタが返されることを読みました。このようにして、free() は解放するメモリの量を認識します。そこで、このサイズを出力する小さなコードを書きました。

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

100 int のスペースを割り当てているので、サイズは 400 になると予想しています。しかし、出力は 409 でした。50 int の出力は 209 で、1000 int の出力は 4009 でした。出力が 9 バイトずれている理由を誰か pls で説明できますか?

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 の倍数になるため、フラグの格納には最下位 3 ビットが使用されます。

/* 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 に答える