技术问询:理解将用户请求大小转为malloc可用大小的宏及相关代码
Alright, let's unpack these macros, type definitions, and the malloc_chunk structure that glibc uses to turn your requested memory size into the actual allocated size under the hood. This is core to how malloc manages memory alignment and chunk metadata.
Core Type & Basic Macro Definitions
First, let's walk through the foundational definitions that power the size conversion logic:
1. INTERNAL_SIZE_T size_t
This is almost certainly a typo in your snippet (it should be typedef INTERNAL_SIZE_T size_t;). It maps the allocator's internal size type to the standard size_t you use in your code—this is the base unit for measuring memory chunks in malloc.
2. #define SIZE_SZ (sizeof(INTERNAL_SIZE_T))
This macro grabs the byte size of the internal size type. For example, if INTERNAL_SIZE_T is 4 bytes (32-bit systems), SIZE_SZ equals 4. It’s used to calculate the footprint of the chunk metadata headers.
3. #define MALLOC_ALIGNMENT MAX(2 * sizeof(INTERNAL_SIZE_T), __alignof__(long double))
This sets the minimum alignment boundary for all allocated memory. It picks the larger of two values to ensure strict alignment:
- Twice the size of
INTERNAL_SIZE_T(guarantees metadata structures are properly aligned) - The alignment requirement of
long double(the strictest alignment need for common data types on most systems)
On 64-bit systems where INTERNAL_SIZE_T is 8 bytes, 2*8=16; if long double requires 16-byte alignment, MALLOC_ALIGNMENT becomes 16.
4. #define MALLOC_ALIGN_MASK (MALLOC_ALIGNMENT - 1)
This is the alignment mask used to quickly round up a requested size to the nearest multiple of MALLOC_ALIGNMENT. The trick looks like this:
aligned_size = (requested_size + MALLOC_ALIGN_MASK) & ~MALLOC_ALIGN_MASK;
Adding the mask and then clearing the lower bits (with ~MALLOC_ALIGN_MASK) ensures aligned_size is always a valid multiple of the alignment boundary.
The malloc_chunk Structure
Every block of memory (allocated or free) in malloc is wrapped in this chunk structure, which holds metadata and linking pointers:
struct malloc_chunk { /* prev_size and size makes the header */ INTERNAL_SIZE_T prev_size; /* Size of previous chunk (if free). */ INTERNAL_SIZE_T size; /* Size in bytes, including overhead. */ struct malloc_chunk* fd; /* double links -- used only if free. */ struct malloc_chunk* bk; struct malloc_chunk* fd; /* Likely a typo; usually fd_nextsize for large free chunks */ };
Let’s break down each field:
prev_size: Only valid if the previous chunk is free. It stores the total size of the prior chunk (including its metadata), which lets malloc merge adjacent free blocks quickly to reduce fragmentation.size: The total size of the current chunk, including the metadata (theprev_sizeandsizefields themselves). A quick note: The last few bits of this value are usually used as flags (e.g., whether the chunk is allocated, whether the previous chunk is free) rather than part of the size.fd&bk: Bidirectional link pointers, only active when the chunk is free. They link the chunk into malloc's free lists, making it easy to find and reuse unused memory.- The duplicate
fdfield is almost certainly a typo. In the actual glibc malloc implementation, large free chunks havefd_nextsizeandbk_nextsizepointers to link chunks of similar sizes, speeding up allocation for larger memory requests.
How It All Comes Together for Size Conversion
When you call malloc(n):
- The requested size
nis rounded up to the nearest multiple ofMALLOC_ALIGNMENTusing theMALLOC_ALIGN_MASKtrick. - The allocator adds the size of the chunk header (2 *
SIZE_SZ, fromprev_sizeandsize) to this aligned value to get the total chunk size. - Malloc finds or reserves a block of this total size, then returns a pointer to the memory immediately after the
malloc_chunkheader—this is the "usable" memory you interact with.
内容的提问来源于stack exchange,提问作者Karim Manaouil

