-
C/C++ Struct Memory Padding프로그래밍/C/C++ 2022. 12. 28. 10:53
C언어 기반으로 Struct를 사용하여 구조체를 생성 했을 경우 다음과 같은 문제를 본적이 있을 것이다.
일반적으로 내가 할당한(할) 타입의 메모리 크기를 보기위해 다음과 같은 코드를 작성한다.
#include <stdio.h> struct MyStruct { char ch; // 1바이트 char * pCh; // 4바이트 int integer; // 4바이트 }; int main() { struct MyStruct custom_type; size_t size = sizeof(custom_type); printf("Size [%d]Byte ", size); }
구조체를 만들고 해당 구조체의 크기를 알아보기 위해 sizeof(struct MyStruct) 또는 sizeof(custom_type) 을 할시 해당 구조체의 할당된 바이트의 크기정보를 반환해준다.
그럼 위 코드에서는 어떠한 결과가 나오게 되겠는가?
일반적으로 주석대로 보면 다음과 같이 정리된다.
char 타입의 경우 1바이트 크기이다.
char 포인터 타입인 경우 4바이트(32비트 컴파일러 기준) 크기이다.
int 타입인 경우 4바이트 크기이다.
그럼 다 합치면 9바이트니까 이 구조체의 크기는 9바이트다.
이러한 결과가 도출될 것이다.
하지만 그렇지 않다, 실제로는 Memory Padding 이라는 것이 존재하게 된다.
메모리 패딩에 대해서는 몰라도 일반적인 멤버접근 방식으로 쓸 때는 지장은 없지만 알면 더욱 효율적인 코드 작성이 가능하다.
메모리 패딩이 뭐냐 ? 하면 위 구조체의 크기 출력 결과를 먼저 봐야 이해가 가능하다.
위 프로그램의 출력의 결과는 "Size [12]Byte" 이다.
멤버변수가 3개이며 각각의 멤버는 32비트 컴파일러 빌드 기준으로 32비트 공간을 할당 받는다.
그러므로 멤버(char) 자료형의 크기는 비록 1바이트 일 지라도 실제로 구조체 내부적으로 할당된 크기는 각각 4바이트 이기 때문이다.
하지만, 바이트 계산에서 원하는 결과를 얻어낼 수 있는 방법은 존재한다.
Visual Studio를 기반으로 코드를 작성하는 경우 다음과 같은 "구조체 멤버 맞춤" 옵션을 제어하면 된다.
설정되어 있는 "기본값"은 컴파일러에 따라 정의된다.
컴파일러 정보 구조체 멤버 맞춤의 기본값 x86 4 Byte x64 8 Byte 그렇다면 위에 옵션을 제어할 수 있다면, 1바이트로 바꿔서 다시 빌드를 해보자.
자 이제 내용을 보면 처음 주석을 작성한 구조체 멤버의 메모리 크기만큼 동일하게 할당이 되어 총 9Byte라는 결과를 도출했다.
그럼 이러한 "구조체 멤버 맞춤" 옵션과 메모리 패딩은 왜 존재하는가 ?
32Bit CPU와 64비트 CPU의 관계에 따라 달라진다.
위에 컴파일러별 Packing 크기에 따라 정의된 것 과 같다.
32bit CPU에서는 메모리에서 하나의 공간을 읽을 때 4바이트 크기 만큼 읽는다.
64bit CPU에서는 메모리에서 하나의 공간을 읽을 때 8바이트 크기 만큼 읽는다.
메모리 공간 자체는 크기가 어마무시하다.
가령 본인 PC의 RAM크기가 1GB 라고 가정을 해보자.
1GB를 4Byte로 나누면 총 1GB를 조회하는데 건너뛰어야 하는 횟수가 정의될 것이다.
그렇다면, 똑같은 크기를 8Byte로 나눠보자.
1GB를 조회하는데 4Byte 크기로 건너뛰어야하는 횟수보다 훨씬 적다.
즉, 메모리 패딩을 맞춤으로써 메모리를 더욱 빠르게 접근하고 찾아낼 수 있다는 것이다.
하지만 이러한 메모리 패딩을 알지 못하면 다음과 같은 세가지 방법중에 한가지만을 선택할 수 밖에 없는 상황이 생긴다.
- 이 메모리 패딩을 이용해서 빠르면서 효율적 사용하는 방법
- 이 메모리 패딩을 이용해서 속도를 얻고, 메모리 효율성을 최악으로 만드는 방법
- 이 메모리 패딩을 이용해서 속도를 낮추고 메모리 효율성을 높이는 방법
이후에 위 세가지 케이스에 대하여 정리를 할 것이다.
'프로그래밍 > C/C++' 카테고리의 다른 글
🖥️ C++에서 윈도우 프로그램 동시 실행 방지하기 (0) 2023.02.28 C++20 코루틴 기능을 활용한 비동기 프로그래밍 예제 (0) 2023.02.23 C++ std::thread와 std::mutex를 사용한 멀티스레딩 예제 (0) 2023.02.22 C++ std::ofstream 사용하는 방법 (0) 2023.02.07 C/C++ 콘솔창에서 커서를 변경해보자 (GetConsoleScreenBufferInfo, SetConsoleCursorPosition) (0) 2023.01.19