Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What guarantees about low order bits does malloc provide?

Tags:

c

malloc

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?

like image 526
compman Avatar asked Jul 12 '11 22:07

compman


People also ask

Does malloc use bits or bytes?

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.

Is malloc 16 byte aligned?

The GNU documentation states that malloc is aligned to 16 byte multiples on 64 bit systems.

How many bytes does malloc use?

Malloc(100) allocates 104 bytes for the user, plus an extra 8 bytes for bookkeeping.

Is malloc a byte?

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.


2 Answers

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.

like image 172
user786653 Avatar answered Oct 22 '22 00:10

user786653


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.

like image 4
antlersoft Avatar answered Oct 22 '22 00:10

antlersoft