When you call C's malloc
, is there any guarantee about what the first few low order bits will be? If you're writing a compiler/interpreter for a dynamic language but want to have fixnums of the form bbbbbbbb bbbbbbbb . . . bbbbbbb1
(where b is a bit) and pointers of the form bbbbbbbb bbbbbbbb . . . bbbbbbb0
(or vice versa), is there any way to guarantee that malloc
will return pointers that fit with such a scheme?
Should I just allocate two more bytes than I need, increment the return value by one if necessary to fit with the bit scheme, and store the actual pointer returned by malloc
in the second byte so that I know what to free
?
Can I just assume that malloc
will return a pointer with zero as the final bit? Can I assume that an x86 will have two zero bits at the end and that an x64 will have four zero bits at the end?
The malloc() function allocates a buffer of size bytes. Use free() or realloc() to free the block of memory. Because the malloc() implementation uses signed, 32-bit integers to represent the size internally, you can't allocate more than 2 GB in a single allocation.
The GNU documentation states that malloc is aligned to 16 byte multiples on 64 bit systems.
Malloc(100) allocates 104 bytes for the user, plus an extra 8 bytes for bookkeeping.
Threadsafe: Yes. The malloc() function reserves a block of storage of size bytes. Unlike the calloc() function, malloc() does not initialize all elements to 0. The maximum size for a non-teraspace malloc() is 16711568 bytes.
C doesn't guarantee anything about the low order bits being zero only that the pointer is aligned for all possibly types. In practice 2 or 3 of the lowest bits will probably be zero, but do not count on it.
You can ensure it yourself, but a better way is to use something like posix_memalign.
If you want to do it yourself you need to overallocate memory and keep track of the original pointer. Something like (assuming you want 16-byte alignment, could be made generic, not tested):
void* my_aligned_malloc16(size_t sz) { void* p = malloc(sz + 15 + 16); // 15 to ensure alignment, 16 for payload if (!p) return NULL; size_t aligned_addr = ((size_t)p + 15) & (~15); void* aligned_ptr = (void*) aligned_addr; memcpy(aligned_ptr, &p, sizeof(void*)); // save original pointer as payload return (void*)(aligned_addr + 16); // return aligned address past payload } void my_aligned_free16(void* ptr){ void** original_pointer = (void**)( ((size_t)ptr) - 16 ); free(*original_pointer); }
As you can see this is rather ugly, so prefer using something like posix_memalign
. Your runtime probably has a similar function if that one is unavailable, e.g. memalign
(thanks @R..) or _aligned_malloc when using MSVC.
Malloc is guaranteed to return a pointer with correct alignment for any data type, which on some architectures will be four-byte boundaries and on others might be eight. You can imagine an environment where the alignment would be one, though. The C library will have a macro somewhere that will tell you what the actual rounding is.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With