开发者

What guarantees about low order bits does malloc provide?

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?


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.


My answer may be slightly off-topic, but my cockpit alarms are going off like mad -- "Pull Up! Pull Up!"

This scheme sounds much too dependent on the HW architecture and the deep implementation details of the compiler and the C libraries. C allows one to get to this level of the nitty-gritty bits and bytes and to peek at the bit pattern and alignment of objects in order to code device drivers and the like. You, on the other hand, are building a high-level entity, a interpreter and run-time. C can do this as well, but you don't have to use C's low-level bit twiddling capabilities; IMHO, you should avoid doing so. Been there, done that, have the holes in the feet to show for it.

If you are successful in creating your interpreter, you will want to port it to a different platform, where the rules about bit representation and alignment can differ, perhaps radically. Coming up with a design that does not depend on such tricky bit manipulation and peeking under the covers will help you immensely down the road.

-k

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜