홍카나의 공부방

[운영체제] 힙 메모리 영역과 스택 메모리 영역 본문

Operating System

[운영체제] 힙 메모리 영역과 스택 메모리 영역

홍문관카페나무 2024. 8. 18. 15:39

 

프로세스의 메모리 사용

 

일반적으로 우리가 사용하는 컴퓨터에서는 프로세스를 메모리에다가 배치할 때 운영체제가 데이터 구조를 아래와 같은 그림으로 배치한다.

 

너무 발로 그렸나?

 

 

...다시 보니까 너무 대충 그렸나 싶기도 하고, 좀 더 자세한 그림을 가져오겠다.

 

https://rninche01.tistory.com/entry/heap1-Dynamic-Memory-Allocation

 

이렇게 된다! 참고로 커널 영역의 경우 운영체제의 영역이니 프로세스의 메모리 구조를 주제로 잡는 이 글에서는 다루지 않겠다. 어떠한 프로그램이 데이터를 저장할 때 여러 영역들에다가 데이터를 나눠서 저장하게 되는데, 영역을 괜히 나눈게 아닐 것이다. 어떤 기준으로 나눴는지 살펴보자.

 

1. 데이터(data) 영역

- 전역 변수, static 변수로 선언한 데이터들이 해당 영역에 들어간다.

- 컴파일 시점에 크기가 결정되며, 프로그램 시작과 동시에 할당되고 종료시 소멸된다.

 

2. 힙(Heap) 영역

- 동적으로 할당된 데이터들이 들어가는 영역이다. ( C에서의 malloc(), C++에서의 new )

- 런타임 시점에서 사이즈가 결정되며, 할당 해제 시점은 C++의 경우 프로그래머가 직접 delete하는 시점이다.

 

3. 스택(Stack) 영역

- 지역 변수와 함수의 매개 변수를 저장한다.

- 컴파일 시점에 크기가 결정되며, 함수가 호출될 시 할당되고 함수가 종료(return)될 때 소멸한다.

 

 

코드 예시로 살펴보자. 아래 C++ 프로그램 코드에서 변수 a가 담고 있는 정수 1은 어느 메모리 영역에 데이터가 할당되었을까?

#include <iostream>

int main()
{
    int a = 1;
    return 0;
}

 

스택 메모리 영역이다. 변수 a는 main() 함수의 지역 변수이고, 컴파일 시점에 4바이트(int 자료형의 크기다.)만큼 스택 메모리에 영역을 차지하게 될 것이다.

 

#include <iostream>

static float d = 3.3;

int* mem_test(int a)
{
    int c = 1;
    return new int(a);
}

int main()
{
    int *main1 = new int(1234);
    int *main2 = mem_test(5678);
    
    delete main1;
    delete main2;
    
	return 0;
}

 

위 코드에서 정수형 포인터 main1, main2와 mem_test 함수 내부에 있는 정수형 변수 c, 그리고 static 정수형 전역 변수 d는 어느 메모리 영역에 할당되었을까?

 

  • main1: 힙 메모리에 할당된 변수
  • main2: 힙 메모리에 할당된 변수 (mem_test 함수에서 할당)
  • c: 스택 메모리에 할당된 지역 변수
  • d: 데이터 영역에 할당된 static 전역 변수

마지막으로 예시로 들진 않았지만 메모리상의 가장 낮은 주소에 위치한 코드(텍스트)영역에는 프로그램 코드들이 실행 가능한 기계어 형태로 들어가게 된다.

 


 

힙 메모리의 데이터 할당

 

힙 메모리 영역에 데이터를 할당하는 것은 Dynamic Memory Allocater가 담당한다. 동적 메모리 관리자라고 번역하던데, 대표적으로 C의 Malloc()이 동적 메모리 관리자 역할을 하는 함수라고 볼 수 있다.

 

Dynamic Memory Allocater는 아래와 같이 두 가지 유형으로 분류할 수 있다.

 

- Explicit Memory Allocator : 응용 프로그램이 allocate와 free 연산을 직접 수행한다. 즉, 프로그래머가 직접 메모리에 데이터를 할당/해제하게 되며, C++에서는 new와 delete 명령어를 이용해서 수행할 수 있다. 프로그래머가 직접 할당/해제한다는 것을 돌려 말하면, 대신 해제해주는 누군가가 없다는 이야기다. 운영체제도 관섭을 안한다! 그래서 항상 new를 쓸 때 delete를 함께 쓰지 않는 실수를 범하지 않도록 주의해야 한다. memory leak이 발생하고 싶지 않다면 말이다......

 

- Implicit Memory Allocator : 응용 프로그램이 allocate만 하고, free 연산은 하지 않는다. 즉, 프로그래머가 직접 힙 메모리 영역 할당을 요청하긴 하는데, 해제 과정은 내부적으로 자동 수행되는 방식이다. 사용하지 않는 Heap 영역을 대신 누군가가 해제해준다는 이야기다. Java의 가비지 콜렉션이 대표적인 예시고, 자바스크립트에서도 가비지 컬렉션이 쉴 새 없이 동작한다.

 

 

 

 

반응형