`aligned_alloc` — 정렬을 지정해 메모리를 할당하는 함수

aligned_alloc — 정렬을 지정해 메모리를 할당하는 함수 (C11)

malloc이 돌려주는 메모리는 어떤 객체든 담을 수 있게 기본 정렬(fundamental alignment)로 맞춰져 있어요. 그런데 캐시라인이나 SSE, VM 페이지 경계처럼 더 엄격한 정렬이 필요한 경우도 있죠. 그럴 때 정렬 크기를 직접 지정해 할당하는 게 aligned_alloc이에요.

출처: cppreference — aligned_alloc

본문

aligned_allocalignment로 지정된 정렬을 갖는, 초기화되지 않은 저장소를 size 바이트만큼 할당해요.

문법

#include <stdlib.h>

void *aligned_alloc( size_t alignment, size_t size );  // (C11부터)

설명

size 매개변수는 반드시 alignment의 정수 배여야 해요.

aligned_alloc은 스레드 안전(thread-safe)해요. 마치 인자를 통해 보이는 메모리 위치만 접근하고 정적 저장소에는 접근하지 않는 것처럼 동작하죠. 한 영역의 메모리를 해제하는 이전의 free, free_sized, free_aligned_sized(C23부터), 또는 realloc 호출은, 같은 영역이나 그 일부를 할당하는 aligned_alloc 호출과 동기화(synchronizes-with)됩니다.

매개변수

매개변수 설명
alignment 정렬을 지정해요. 구현이 지원하는 유효한 정렬이어야 합니다.
size 할당할 바이트 수. alignment의 정수 배여야 해요.

반환값

성공하면 새로 할당된 메모리의 시작을 가리키는 포인터를 돌려줘요. 메모리 누수를 막으려면 돌려받은 포인터를 freerealloc로 해제해야 합니다. 실패하면 널 포인터를 돌려줍니다.

주의

sizealignment의 정수 배가 아니거나, alignment가 유효하지 않거나 구현이 지원하지 않는 값이면 함수는 실패하고 널 포인터를 돌려줘요. (C11이 처음 발표됐을 때는 이 경우 동작이 정의되지 않는다고 되어 있었는데, DR460으로 시정됐습니다.) 제한적인 정렬 경계에 작은 객체를 할당할 수 있게 크기 제한을 없애자는 제안(N2072)도 있었어요.

"구현이 지원하는 정렬"이 무슨 뜻인지 예를 들어볼게요. POSIX의 posix_memalign은 2의 거듭제곱이면서 sizeof(void *)의 배수인 정렬을 받아들이는데, POSIX 기반의 aligned_alloc 구현도 이 요구를 그대로 물려받아요.

기본 정렬은 항상 지원됩니다. alignment가 2의 거듭제곱이고 _Alignof(max_align_t)보다 크지 않다면, aligned_alloc은 그냥 malloc을 호출할 수도 있어요.

여기서 malloc과의 차이를 한 번 더 짚어볼게요. 일반 malloc은 기본 정렬을 가진 어떤 객체 타입에도 맞는 메모리를 정렬하지만, aligned_alloc은 SSE, 캐시라인, VM 페이지 경계 같은 과정렬(over-aligned) 할당에 유용합니다.

이 함수는 Microsoft C 런타임 라이브러리에서는 지원되지 않아요. MS의 free 구현이 어떤 정렬 할당도 다룰 수 없기 때문이에요. 대신 MS CRT는 _aligned_malloc(해제는 _aligned_free로)을 제공합니다.

예시

기본 정렬된 malloc 주소와 1024바이트 정렬된 aligned_alloc 주소를 비교하는 예시예요.

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

int main(void)
{
    int *p1 = malloc(10 * sizeof *p1);
    printf("default-aligned addr:   %p\n", (void*)p1);
    free(p1);

    int *p2 = aligned_alloc(1024, 1024 * sizeof *p2);
    printf("1024-byte aligned addr: %p\n", (void*)p2);
    free(p2);
}

가능한 출력:

default-aligned addr:   0x1e40c20
1024-byte aligned addr: 0x1e41000

aligned_alloc(1024, ...)으로 할당한 주소 0x1e41000은 1024(=0x400)로 나누어떨어지는, 즉 1024바이트 경계에 정렬된 주소라는 걸 확인할 수 있어요.

더 알아보기

  • malloc — 메모리를 할당해요.
  • free_aligned_sized — 정렬되고 크기가 지정된 메모리를 해제해요 (C23).
  • cppreference의 aligned_alloc 원문에서 표준 항목별 세부 규칙을 더 확인할 수 있어요.