dryajov
dryajov

Reputation: 455

Question about pointer alignment

I'm working on a memory pool implementation and I'm a little confused about pointers alignment...

Suppose that I have a memory pool that hands out fixed size memory blocks, at the point of memory pool creation I malloc((size)*(num of blocks)). If what's being allocated are objects and the size comes from the sizeof operator alignment shouldn't be a concern, but if the size is uneven (he/she wants 100 byte blocks for whatever reason), then when I split the chunk given by malloc I'd end up with unaligned pointers. My question is should I always align the blocks to some boundary and if yes which?

Upvotes: 2

Views: 428

Answers (2)

Alex Martelli
Alex Martelli

Reputation: 882791

Proper alignment is at least helpful (performance-wise) on most x86 implementations (and some kind of alignment is actually mandatory in other architectures). You might ask (like calloc does) for a pair of arguments, size of items in bytes and number of items, rather than just one (size in bytes, like malloc does); then you can intrinsically align (by rounding up block sizes) to the next-higher power of 2 above the item size (but switch to multiples of 16 bytes above 16, don't keep doubling forever, just like @derobert recommends and explains!-). This way, if a caller just wants N bytes w/o any alignment nor padding, they can always ask for N items of 1 byte each (just like they would with calloc and for the same reason;-).

Upvotes: 3

derobert
derobert

Reputation: 51207

X86 will work without alignment, but performance is better when data is aligned. Alignment for type is generally sizeof(type), up to a maximum of 16 (bytes).

I wrote this silly test program just to be sure (asuming malloc knows what its doing), and it returns 16 on my amd64 box. It returns 8 when compiled in 32-bit mode:

#include <stdlib.h>
#include <stdio.h>

int main() {
    int i;
    unsigned long used_bits = 0, alignment;

    for (i = 0; i < 1000; ++i) {
        used_bits |= (unsigned long)malloc(1);   /* common sizes */
        used_bits |= (unsigned long)malloc(2);   
        used_bits |= (unsigned long)malloc(4);
        used_bits |= (unsigned long)malloc(8);
        used_bits |= (unsigned long)malloc(16);
        used_bits |= (unsigned long)malloc(437); /* random number */
    }

    alignment = 1;
    while (!(used_bits & alignment)) {
        alignment <<= 1;
    }

    printf("Alignment is: %lu\n", alignment);
    return 0;
}

Upvotes: 2

Related Questions