24

How do you allocate memory that's aligned to a specific boundary in C (e.g., cache line boundary)? I'm looking for malloc/free like implementation that ideally would be as portable as possible --- at least between 32 and 64 bit architectures.

Edit to add: In other words, I'm looking for something that would behave like (the now obsolete?) memalign function, which can be freed using free.

fuad
  • 4,265
  • 9
  • 34
  • 32
  • Have you checked these two answers on SO: http://stackoverflow.com/questions/227897/solve-the-memory-alignment-in-c-interview-question-that-stumped-me/227900#227900 and http://stackoverflow.com/questions/1855896/memory-alignment-on-modern-processors? – Mike Dinescu Dec 17 '09 at 03:01
  • Not quite what I'm looking for. I would like something that functions more like malloc, returns one value that is the aligned pointer, then have another function similar to free, that's called on that pointer. Applying a solution such as the ones you pointed requires either passing around two values, or recalculating the alignment whenever it's needed. I'm looking for something similar to memalign. Thanks for pointing those answers out though. – fuad Dec 17 '09 at 03:32
  • 1
    There's `posix_memalign()` on appropriate machines - has a different interface from `memalign()`. – Jonathan Leffler Dec 17 '09 at 03:38
  • 1
    Possible duplicate of [aligned malloc() in GCC?](http://stackoverflow.com/questions/3839922/aligned-malloc-in-gcc) – Ciro Santilli OurBigBook.com Mar 16 '17 at 07:22

3 Answers3

26

Here is a solution, which encapsulates the call to malloc, allocates a bigger buffer for alignment purpose, and stores the original allocated address just before the aligned buffer for a later call to free.

// cache line
#define ALIGN 64

void *aligned_malloc(int size) {
    void *mem = malloc(size+ALIGN+sizeof(void*));
    void **ptr = (void**)((uintptr_t)(mem+ALIGN+sizeof(void*)) & ~(ALIGN-1));
    ptr[-1] = mem;
    return ptr;
}

void aligned_free(void *ptr) {
    free(((void**)ptr)[-1]);
}
jer
  • 20,094
  • 5
  • 45
  • 69
Jerome
  • 2,350
  • 14
  • 25
  • 2
    with the new standards, you should consider replacing the cast to `long` with a cast to `uintptr_t` – Ryan Haining Feb 14 '13 at 22:46
  • @Jermoe In particular, the code does not work on 64-bit Windows – user877329 Jun 29 '15 at 14:49
  • @Jerome — Any particular reason you say `malloc(size+ALIGN+sizeof(void*))` and not `malloc(size+ALIGN-1+sizeof(void*))`? If you're aligning to an *n*-byte boundary, then you only ever need at most *n* – 1 extra bytes. – Todd Lehman Aug 21 '15 at 05:17
  • This code is somewhat confusing in its use of the void** in the return statement. – einpoklum Oct 22 '15 at 16:26
  • Is it okay to add +ALIGN-1 instead of +ALIGN? void *aligned_malloc(int size) { void *mem = malloc(size+ALIGN-1+sizeof(void*)); void **ptr = (void**)((long)(mem+ALIGN-1+sizeof(void*)) & ~(ALIGN-1)); ptr[-1] = mem; return ptr; } – Dewr Nov 01 '15 at 23:54
  • so when you free you get a cache miss – Gabriel May 14 '19 at 18:09
  • How is this different from free(ptr)? – Vincent Alex Jul 20 '22 at 12:48
15

Use posix_memalign/free.

int posix_memalign(void **memptr, size_t alignment, size_t size); 

void* ptr;
int rc = posix_memalign(&ptr, alignment, size);
...
free(ptr)

posix_memalign is a standard replacement for memalign which, as you mention is obsolete.

Lucian Adrian Grijincu
  • 2,491
  • 2
  • 18
  • 18
4

What compiler are you using? If you're on MSVC, you can try _aligned_malloc() and _aligned_free().

cxxl
  • 4,939
  • 3
  • 31
  • 52
mrkj
  • 3,041
  • 19
  • 24
  • Sun's compiler for Solaris/SPARC and gcc for Linux/x86 – fuad Dec 17 '09 at 03:43
  • 1
    Looks like Sun supports memalign(): http://docs.sun.com/app/docs/doc/816-5168/malloc-3c?a=view I don't see any indication that memalign() is deprecated in the current glibc: http://cvs.savannah.gnu.org/viewvc/libc/malloc/malloc.h?revision=1.32&root=libc&view=markup – mrkj Dec 17 '09 at 03:49
  • Links that work: [_aligned_free](https://learn.microsoft.com/en-us/cpp/c-runtime-library/reference/aligned-free?view=msvc-170), [_aligned_malloc](https://learn.microsoft.com/en-us/cpp/c-runtime-library/reference/aligned-malloc?view=msvc-170). – Daniel Feb 03 '22 at 19:01