Developer Jay

[C/C++] 바이트패딩과 구조체패딩!

22 May 2022

Intro

바이트패딩, 구조체패딩의 규칙과 패딩이 발생하는 이유에 대해 알아보자


1. 패딩

image

  • 위 화면의 구조체 크기는 몇 byte 일까? 잠시 생각해보고 답을 확인해보도록 하자
  • 구조체 크기는 2byte(short) + 4byte(int) + 1byte(char)로 7byte 가 되어야할 것 같지만 놀랍게도 패딩 규칙 적용으로 인해 아래와 같이 12byte 가 된다. image
  • 그렇다면 패딩이 발생하는 규칙과 그 이유는 무엇일까?


1.1 바이트 패딩

  • 바이트 패딩이 생긴 이유는 모든 변수들이 자신의 크기의 배수로 정렬되는 것이 좋기 때문이다. 이 내용은 캐시메모리와 밀접한 연관이 있다.
  • 이전에 다룬 캐시메모리 포스트에서 “CPU는 데이터 지역성의 원리를 사용하여 연속된 64Byte 의 data를 가져와 캐시메모리에 적재한다” 라고 하였다.
  • 만약, 변수들을 자신의 크기의 배수로 정렬하지 않고서 64byte 단위로 캐시메모리에 데이터를 적재한다면 어떻게 될까?
  • 캐시라인 경계(64^n)에 걸친 데이터는 CPU가 메모리에 두번 접근하여 가져와야 할 수도 있으므로 처리 속도가 그만큼 느려지게 된다.
  • 내용을 정리하자면 메모리 공간이 낭비되는 한이 있더라도 CPU의 처리속도를 높이기 위해 바이트 패딩이 등장하였다.
  • 따라서 위 화면의 stTest 구조체에서 short a 뒤에 있는 int b 는 자신의 크기의 배수로 정렬하기 위해 2byte 만큼 패딩을 적용하였다.


1.2 구조체 패딩

  • 조금 생각해보면 위 화면의 stTest 구조체에서 맨 뒤의 3byte 패딩은 필요 없을 것 같다. 중간에 넣은 2byte 패딩으로 인해 변수 a, b, c의 경계가 모두 정렬이 된 것 같으니 말이다.
  • 바이트 패딩만 적용된 것이 아니라 맨 뒤에 3byte 의 패딩이 적용된 이유는 무엇일까?
  • 구조체 맨 뒤에 패딩을 넣는 이유는 구조체가 배열로 사용될 때 각 구조체의 시작 경계가 메모리의 정렬된 위치에 올라가도록 하기 위함이다.
  • 따라서 구조체는 구조체 안에서 가장 큰 변수의 크기에 맞추어 구조체의 맨 뒤에 패딩을 적용한다. 위 화면의 stTest 구조체에서 가장 큰 변수인 int 에 맞추어 정렬하기 위해 맨 뒤에 3byte 만큼 패딩을 적용하였다.


[TIP] 패딩 제거 방법

  • CPU 처리속도를 높이기 위해 패딩 비트를 적용하여 메모리 공간을 낭비 시킨다고 하였다.
  • 구조체를 네트워크로 전송하는 경우 패딩 비트로 인해 트래픽 양이 증가한다.
  • 이러한 경우 패딩 비트를 pragma pack(n) 지시자로 제거할 수 있다. CPU 처리속도가 늦어지더라도 네트워크 트래픽양을 줄이는 것이다.
  • pragma(n) 지시자는 범위 내 모든 구조체의 기준 바이트를 n으로 만든다. 따라서 만약 n을 1로 두게 되면 모든 패딩 비트가 사라지게 된다.
  • pragma(n) 지시자의 범위 지정 방법은 아래와 같다.

image