기초 CS - 구조체 메모리 정렬

킴스코딩클럽·2022년 9월 20일
1

CS기초 시리즈

목록 보기
5/71

데이터 관리나 네트워크 통신에서 자주 사용되는 메모리 정렬
운영체제가 바뀌거나 네트워크 환경 변화에 의해서 오류가 나는 경우, 클라이언트에서 서버로 보낼 때 메모리 크기가 변경되는 경우가 있음

자료형의 바이트 크기를 구하는 연산자 SIZEOF

struct guessByte1
	{
		char guessChar;
	};

	std::cout << sizeof(guessByte1) << std::endl;

struct guessByte2
	{
		char guessChar;
		int guessInt;
	};
	std::cout << sizeof(guessByte2) << std::endl;

구조체 guessByte1는 1byte
guessByte2는 5byte라고 예상해 볼 수 있다
하지만 결과는
guessByte1는 1byte
guessByte2는 8byte

컴파일러가 메모리 관리의 효율성을 위해서 구조체 멤버들의 크기를 조정하기 때문이다


윈도우 환경에서 메모리를 효율적으로 관리하기 위해서, 컴퓨터 메모리가 8G라고 가정했을 떄, 8 x 1024 x 1024 크기의 메모리 공간을 4개(4BYTE)묶어서 계산하는 바이트 정렬(alignment) 방식을 사용한다. 4바이트 단위로 주소를 관리하기 위해서 1바이트 뒤에 3바이트의 padding을 추가해 4바이트로 관리하게 된다

struct S1
	{
		char myChar;
	};
struct S2
	{
		char myChar1;
		char myChar2;
		int myInt1;
		int myInt2;
	};

	std::cout << sizeof(S2) << std::endl; 

S2의 크기는 10으로 생각할 수 있지만 결과는 12가 나온다 

클라이언트는 대부분 윈도우 환경이고 서버는 대부분 리눅스 환경으로
윈도우 환경에서는 4바이트 정렬을 사용하지만 리눅스는 1바이트 정렬을 사용한다 이 것은 모두 운영체제가 메모리를 관리하기 때문에 생기는 일
하지만 클라이언트와 서버가 네트워크로 통신하면 데이터를 정확하게 맞춰서 최소화 시켜야 통신 효율성이 증가함 그래서 바이트 숫자를 맞춰야할 상황이 생길 수 있음


해결책

#pragma 지시자 사용
컴파일러의 여러가지 도움이 되는 정보를 수정할 수 있는 지시자 중 구조체의 바이트를 관리하는 pack() 기능을 사용
packing은 push, pop용어를 이용해 바이트를 묶을 기준을 관리할 수 있다

#pragma pack(push,1)

	struct guessByte2
	{
		char guessChar;
		int guessInt;
	};
#pragma pack(pop)
#pragma pack(push,1) 
// 1바이트 단위로 메모리를 패킹한다는 정보를 보냄 
// 이 라인 이후는 모두 1바이트 단위로 패킹됨을 뜻함
#pragma pack(pop)
// 패킹 정보를 꺼냄
// 1바이트 단위 패킹을 꺼내고 기본값으로 되돌아감
profile
공부 기록용

0개의 댓글