-
64비트 시스템에서 메모리 정렬 경계에 대해개발/C·C++ 2024. 10. 11. 14:52
64bit 프로세서의 64bit 모드에서 메모리 동적할당을 하면 주소 값이 16바이트 정렬이 기본 값인 것 같다.
struct PureNode { int a; int b; int c; }; int main() { constexpr int ALIGN = 16; for (int i = 0; i < 10000; ++i) { uintptr_t node1 = reinterpret_cast<uintptr_t>(new PureNode()); uintptr_t node2 = reinterpret_cast<uintptr_t>(new PureNode()); uintptr_t node3 = reinterpret_cast<uintptr_t>(new PureNode()); uintptr_t node4 = reinterpret_cast<uintptr_t>(new PureNode()); uintptr_t node5 = reinterpret_cast<uintptr_t>(new PureNode()); ASSERT_CRASH(node1 % ALIGN == 0); ASSERT_CRASH(node2 % ALIGN == 0); ASSERT_CRASH(node3 % ALIGN == 0); ASSERT_CRASH(node4 % ALIGN == 0); ASSERT_CRASH(node5 % ALIGN == 0); delete reinterpret_cast<PureNode*>(node1); delete reinterpret_cast<PureNode*>(node2); delete reinterpret_cast<PureNode*>(node3); delete reinterpret_cast<PureNode*>(node4); delete reinterpret_cast<PureNode*>(node5); } }
ASSERT_CRASH 매크로 함수는 표현식이 거짓일 경우 크래시를 내도록 되어 있다. 기본으로 제공되는 _ASSERT 매크로 함수는 디버그 모드에서만 동작하기 때문에 테스트 할 때는 디버그/릴리즈 모든 환경에서 검사하는 게 목적이었으므로 별도로 만들었다.
32bit 모드로 설정하니 8바이트가 기본 정렬인 것 같다.
기본값이 있다고 해도 실제 개발할 때는 가독성과 확실함을 보장받기 위해 __declspec(align(x))를 써주도록 하자. 특히 MS에서 제공하는 SLIST 시리즈를 사용할 때는 메모리를 16바이트 경계에 놓는 것이 필수다.
__declspec(align(16)) struct PureNode { int a; int b; int c; };
참고로 구조체를 __declspec(align(16))로 설정하고 32비트 모드에서 동적으로 메모리를 할당하면 비주얼 스튜디오 2022에서는 컴파일 단계에서 다음과 같은 경고를 내준다.
'개발 > C·C++' 카테고리의 다른 글
[Protobuf 따라하기] 수신 데이터를 복사 없이 가공하기 (1) 2024.11.08 VirtualAlloc()의 메모리 할당에 대해 (0) 2024.10.12 포인터 붕괴와 붕괴가 아닌 것 (0) 2024.09.28 덧셈 연산 어셈블리 코드 간단 분석 (1) 2024.09.07 std::transform()에 대한 간단한 고찰 (2) 2024.09.04