> C and C++ have aligned_alloc for a while now, which should work everywhere as > long as the compiler is somewhat up to date (C11/C++17).
Just be aware of the different argument order on Windows. These are my aligned_alloc primitives: <https://github.com/mratsim/weave-io/blob/8672f1cc4182633a9e31a2eb6641e941926b869d/weave_io/primitives/allocs.nim#L42-L55> when defined(windows): proc aligned_alloc_windows(size, alignment: int): pointer {.tags:[HeapAlloc],importc:"_aligned_malloc", header:"<malloc.h>".} # Beware of the arg order! proc aligned_alloc(alignment, size: int): pointer {.inline.} = aligned_alloc_windows(size, alignment) proc aligned_free(p: pointer){.tags:[HeapAlloc],importc:"_aligned_free", header:"<malloc.h>".} elif defined(osx): proc posix_memalign(mem: var pointer, alignment, size: int){.tags:[HeapAlloc],importc, header:"<stdlib.h>".} proc aligned_alloc(alignment, size: int): pointer {.inline.} = posix_memalign(result, alignment, size) proc aligned_free(p: pointer) {.tags:[HeapAlloc], importc: "free", header: "<stdlib.h>".} else: proc aligned_alloc(alignment, size: int): pointer {.tags:[HeapAlloc],importc, header:"<stdlib.h>".} proc aligned_free(p: pointer) {.tags:[HeapAlloc], importc: "free", header: "<stdlib.h>".} Run and then I build these high-level wrappers on top: <https://github.com/mratsim/weave-io/blob/8672f1cc4182633a9e31a2eb6641e941926b869d/weave_io/primitives/allocs.nim#L100-L133> proc allocHeapAligned*(T: typedesc, alignment: static Natural): ptr T {.inline.} = # aligned_alloc requires allocating in multiple of the alignment. let # Cannot be static with bitfields. Workaround https://github.com/nim-lang/Nim/issues/19040 size = sizeof(T) requiredMem = size.roundNextMultipleOf(alignment) cast[ptr T](aligned_alloc(alignment, requiredMem)) proc allocHeapUncheckedAligned*(T: typedesc, size: int, alignment: static Natural): ptr T {.inline.} = ## Aligned heap allocation for types containing a variable-sized UncheckedArray field ## or an importc type with missing size information # aligned_alloc requires allocating in multiple of the alignment. let requiredMem = size.roundNextMultipleOf(alignment) cast[ptr T](aligned_alloc(alignment, requiredMem)) proc allocHeapArrayAligned*(T: typedesc, len: int, alignment: static Natural): ptr UncheckedArray[T] {.inline.} = # aligned_alloc requires allocating in multiple of the alignment. let size = sizeof(T) * len requiredMem = size.roundNextMultipleOf(alignment) cast[ptr UncheckedArray[T]](aligned_alloc(alignment, requiredMem)) proc allocHeapAlignedPtr*(T: typedesc[ptr], alignment: static Natural): T {.inline.} = allocHeapAligned(typeof(default(T)[]), alignment) proc allocHeapUncheckedAlignedPtr*(T: typedesc[ptr], size: int, alignment: static Natural): T {.inline.} = ## Aligned heap allocation for types containing a variable-sized UncheckedArray field ## or an importc type with missing size information allocHeapUncheckedAligned(typeof(default(T)[]), size, alignment) proc freeHeapAligned*(p: pointer) {.inline.} = aligned_free(p) Run