struct, class의 메모리 allocation

김대익·2022년 2월 18일
0
#include <iostream>
using namespace std;
struct ST {
	long a;
    int b;
    short c;
}

int main() {
	cout << sizeof(ST) << '\n';
    return 0;
}

의 경우 long = 8bytes, int = 4bytes, short = 2bytes이므로 14bytes로 예상하지만
결과는 16bytes가 나온다.
이는 memory access pattern때문에 컴파일러가 알아서 사이에 paddding을 넣어준다.


memory access pattern

struct ST {
	char c1;
   int i4a;
   int i4b;
   double d8;
}

의 경우
c1 1bytes는 그냥 들어간 뒤 4의 배수로 밖에 들어갈 수 없는 int를 위해 3bytes padding이 생기고
int들은 그대로 4의 배수로 4bytes씩 들어간 뒤
double은 8bytes로 8의 배수로 밖에 memory allocation을 할 수 없으므로 8의 배수인 16을 만들기 위해 4bytes padding을 주고 8bytes가 들어가서
총 24bytes크기의 구조체가 된다.

CPU의 캐시라인

  • CPU가 메모리로부터 데이터를 가져올 때는 바이트 단위로 가져오지 않고 캐시라인을 가득 채울 만큼의 데이터를 가져오는 것
  • 멀티프로세서의 경우 같은 캐시메모리를 참조할 수 있으므로 거의 동시에 참조하고 첫 번째로 접근한 CPU가 수정을 할 경우
    두 번째로 접근한 CPU가 갱신되기 이전의 값을 읽어오는 문제가 생길 수 있다.

#include <iostream>
class Cat
{
public:
	void printCat();
private:
	int age;
	int weight;
};
int main()
{
	Cat cat1;
	Cat cat2;

	Cat * catPtr = &cat1;
	std::cout << sizeof(catPtr) << std::endl;
	
	return 0;	
}

라고 할 경우
int가 2개이므로 구조체의 크기는 8bytes라고 생각할 수도 있고
멤버함수 printCat()가 있으므로 이 함수를 가르키는 포인터가 생겨 이 포인트를 저장하기 위해 8bytes가 추가되어 구조체의 크기는 16bytes라고 생각할 수도 있다.
답은 8bytes로 함수는 구조체 크기에 영향을 미치지않는다.

64bits환경에서 포인터는 type에 상관없이 항상 8bytes를 갖는다(64bits = 8bytes이므로 주소 표현시 8bytes)

0개의 댓글