반응형

프로그램을 실행하면 운영체제는 우리가 실행시킨 프로그램을 위해 메모리 공간을 할당합니다. 할당되는 메모리 공간은 크게 스택(Stack), 힙(Heap), 데이터(Data) 영역으로 나뉘어집니다. 이러한 메모리 공간이 왜, 어디서 할당되는지를 알아보도록 하겠습니다.

 
 
 

메모리 공간의 할당 시기는 프로그램이 실행될 때마다 할당이 됩니다. 할당이 되는 장소론 메인 메모리(RAM)이며, 할당 용도로는 프로그램 실행 시 필요한 메모리 공간(지역변수, 전역변수 선언을 위해) 할당이 됩니다.

 

할당 시기 : 프로그램이 실행될 때마다
할당 장소 : 메인 메모리(RAM)
할당 용도 : 프로그램 실행 시 필요한 메모리 공간(지역변수, 전역변수 선언을 위해) 할당

 

 

 

 

 

 

데이터 영역

전역 변수와 static 변수가 할당되는 영역

프로그램의 시작과 동시에 할당되고, 프로그램이 종료되어야 메모리에서 소멸됨

#include <stdio.h>

int a = 10; // 데이터 영역에 할당
int b = 20; // 데이터 영역에 할당

int main() {
	...
    return 0;
}

위와 같은 코드에서 int형 변수 a, b는 프로그램 실행시, main 함수가 호출되기 전에 데이터 영역에 할당됩니다. 그렇기 때문에 프로그램이 종료될 때까지 메모리상에 존재합니다. 이 때문에 전역변수가 프로그램이 종료될 때까지 존재하는 이유입니다.

 

 

 

 

 

 

 

스택 영역

함수 호출 시 생성되는 지역 변수와 매개 변수가 저장되는 영역

함수 호출이 완료되면 사라짐

 

#include <stdio.h>

void fct1(int);
void fct2(int);

int a = 10; // 데이터 영역에 할당
int b = 20; // 데이터 영역에 할당

int main() {
	int i = 100; // 지역변수 i가 스택 영역에 할당
    
    fct1(i);
    fct2(i);
    
    return 0;
}

void fct1(int c) {
	int d = 30; // 매개변수 c와 지역변수 d가 스택영역에 할당
}

void fct2(int e) {
	int f = 40; // 매개변수 e와 지역변수 f가 스택영역에 할당
}

main함수와 fct1, fct2라는 함수를 추가했습니다. a, b를 데이터 영역에 할당한 뒤에 main함수를 호출하며 int형 변수 i는 지역변수로서 스택영역에 할당됩니다.

그 뒤에 fct1()이라는 함수를 호출하면서 fct1함수의 매개변수인 c와 d가 스택영역에 할당됩니다. fct1()이라는 함수호출이 끝나면 c와 d는 스택영역에서 삭제되며, 그 뒤 fct2()라는 함수를 호출하면서 매개변수 e와 지역변수 f가 스택영역에 할당됩니다.

스택영역은 그 이름 그대로 스택의 성질을 띄고 있습니다.

 

두 번째 블락의 그림에서 'e=100, f=40'이 삭제되었는데 'c=100, d=30'이 삭제되었어야 맞습니다.

 

 
 
 
 
 
 

힙 영역

필요에 의해 동적으로 메모리를 할당 할 때 사용

지금까지 데이터영역과 스택영역을 알아보았는데, 저 두가지 영역만 있으면 코드를 문제없이 짤 수 있을 것처럼 보입니다. 그렇다면 힙 영역은 왜 필요할까요?

 

힙 영역은 프로그래머가 할당한다고 했습니다. 그럼 언제 할당을 하게 될까요?? 배열을 예로 들어보도록 하겠습니다.

 

저흰 배열을 선언할 때 상수로 선언합니다.

int main() {
	// 정상적인 배열선언
    int arr[10];
    
    // 비 정상적인 배열선언
    int i = 0;
    scanf("%d", &i);
    int arr[i];
    
    return 0;
}

배열의 길이를 사용자가 입력한 숫자로 잡아주는 건 비 정상적인 배열선언입니다. 왜그럴까요?

이 점을 알기위해선 메모리 구조에 대해 파악해야 합니다.

 

제일 처음 그림을 보도록 합시다. 스택 영역에 할당될 메모리의 크기는 컴파일 타임(컴파일 하는 동안)에 결졍된다고 되었습니다.

그렇다면 arr의 배열 크기는 40바이트인 것을 알 수 있습니다. 하지만 비 정상적인 배열선언의 경우 i의 크기가 4바이트 라는 것을 알 수는 있으나, arr이라는 배열의 크기는 알 수 없습니다.

 

그렇다면 다음과 같이 배열을 선언할 때는 문제가 없을까요?

 

 

 

 

int main() {
	int i = 10;
    int arr[i];
    
    return 0;
}

i라는 변수가 10이기 때문에 arr이라는 배열의 크기가 10이라는 것을 알 수 있을까라고 예상할 수 있습니다. 하지만 그렇지 않습니다.

 

컴파일을 하는 동안 i가 4바이트의 크기인 것을 알 수 있으나, 그 값이 10이라는 것은 무시하고 넘어갑니다. 사실 값이 10이라는 것은 실행되는 동안, 즉 런타임에 결정됩니다. 그렇기 때문에 컴파일러는 arr의 크기가 40바이트가 된다는 것을 그 때 알 수 있습니다.

 

사용자의 요구에 맞게 메모리를 할당해 주기 위해선(런타임에 메모리 크기를 결정하고 싶을 때) 메모리 동적 할당을 통해 힙 영역에 메모리를 할당해야 합니다.

 

힙 영역 : 할당해야 할 메모리의 크기를 프로그램이 실행되는 동안 결정해야 하는 경우(런타임 때) 유용하게 사용되는 공간

 

힙 영역을 사용하기 위해선 동적할당에 대해서 공부해야 합니다. 이 점은 다음 글에서 다루도록 하겠습니다.

+ Recent posts