SWjungle/#컴퓨터시스템

메모리 정렬과 패딩

장영 2023. 9. 9. 20:19

📌클래스의 멤버가 저장되는 영역 및 메모리 차지

  • 우선 클래스는 멤버 변수와, 멤버 함수를 가질 수 있고, 정적 그리고 비정적 멤버 변수, 함수를 가질 수 있다.
  • 클랙스 타입의 객체 또는 인스턴스 자체의 크기는 비정적 멤버 변수만 영향을 미친다.
  • 즉, 멤버 변수로 int형 변수 1개를 가지면 이 클래스의 인스턴스 sizeof는 4바이트, 2개를 가지면 8바이트, 비정적 멤버 변수는 객체 생성과 동시에 생성된다. 객체 내의 지역변수와 동일하므로 스택에 저장된다. 또한 비정적 멤버 변수는  클래스 내에서 공유되는 변수가 아닌 하나의 객체마다 할당되는 변수이다.
  • 만약 클래스 내에 정적 멤버 변수를 선언했다면 이 변수는 객체 생성 시 할당되는 것이 아니라 프로그램 시작시 데이터 영역에 생성된다. 따라서 정적 멤버 변수는 객체의 크기에 영향을 미치지 않는다. int형 변수 2개와 static int형 변수 1개를 멤버로 가지는 클래스로 예를들면, 프로그램 시작 시 static int 타입 변수가 하나 생성되며, 해당 객체를 생성할 때 int형 변수 2개를 가진 객체가 생성된다. 이 객체의 sizeof 는 8바이트다. 정적 멤버 변수는 객체마다 할당되는 변수가 아니기 때문에 해당 클래스로 생성되는 모든 객체가 공유하는 1개의 변수이며 프로그램 시작 시 데이터 영역에 저장된다.
  • 함수멤버도 동일하게 정적과 비정적으로 나뉘며, 함수는 정적, 비정적 객체의 크기에 영향을 미치지 않는다. 멤버 함수는 모드 code에 저장된다.

📌메모리 상에 클래스 또는 구조체 저장

#include <stdio.h>

struct temp {   

    int num;
    char c1;
    char c2;
};

int main(void) {
    printf("구조체 temp의 크기 : %lu\n", sizeof(struct temp));
    return 0;
}

  • 6바이트가 나와야하지만 8바이트가 나오게 된다. 이는 클래스도 마찬가지이다.
  • 왜 이렇게 되는가?

 

 

💡프로세스의 메모리 접근단위

  • 기본적으로 해당 코드를 실행하면 메모리로 올라간다.
  • 그리고 프로세스는 함수가 실행 될 때마다 변수의 주소값을 통해 메모리로 접근해 원하는 정보를 가져온다.
  • char[10]이라는 배열이 있다고 했을 때, 프로세스는 해당 자료를 어떻게 접근할까 ?

  • 프로세스는 데이터에 접근할 때 최소 2바이트 단위로 접근하게 된다.
  • 2, 4, 8, 16, 32 바이트까지 한번에 가져와 처리하게 된다.
  • 보통은 1word (4바이트) 단위로 가져온다.

 

💡데이터가 정렬되지 않았을때

  • int num과 char c1, c2에 접근할때는 문제 없지만,  문제는 num2에서 생긴다.
  • 주소값에 접근할때 2byte, 4byte 단위로 읽어오게 되는데 위에서는 4byte단위로 읽어오게 된다.
  • 즉, 컴파일러는 6의 위치부터 읽어오는게 아닌 8부터 읽어오게 된다.
  • 이는 int 때문인데, 자료형이 큰 순서로 데이터를 읽어오게 된다.
  • 만약 double이 있다면 8바이트씩 읽어오게 된다. 그리고 프로세스는 잘린 num을 받게되고 다시 메모리에 접근하게 된다.

  • 이런식으로 진행된다. 데이터 양이 많을 수록 한번 처리할걸 두번 처리하기 때문에 성능 저하가 일어난다.
  • 이런 현상을 해결하고자 데이터 자료형을 갖고있는 데이터들 중 가장 큰 데이터의 값을 기준으로 패딩시켜준다.

 

💡데이터가 정렬 되었을때

  • 때문에 위 예제에서 8바이트는 int자료형에 맞춰 남은 부분을 패딩으로 넣어 8바이트가 잡히는 것이다.