본문 바로가기
CS/컴퓨터 과학 얕은 지식

Heap 이란? (뜻, 목적, 사용 시 문제 (Memory leak, Memory Fragmentaion), 해결 방법)

by Unagi_zoso 2022. 4. 16.

컴퓨터에 대하여 공부를 하는 사람이라면

Heap 메모리 영역이란 말을 많이 들어봤을 것이다.

c, c++을 공부하는 입장이라면 특히 말이다.

 

Heap에 대한 설명 이전에 메모리의 영역이 어떻게 나눠지는지에 대해 간략히 설명하겠다.

 

컴퓨터의 메모리 영역

 

컴퓨터의 메모리 영역은 다음 이미지 파일과 같이 분류할 수 있다. 

 

STACK 영역에서는 프로그램이 실행되고 프로세스 진행에 따라 지역변수, function콜에 잇따른

frame 단위의 데이터들이 생성되었다, 사라진다

STACK 영역은 보통 1MB 정도의 크기로 할당된다(확장 가능).

 

HEAP 영역에서는 프로그램이 실행되고 있는 시기에 (runtime) 데이터를 할당할 때

그 데이터를 만들어지는 영역이다.

 

위 이미지 파일에서 볼 수 있듯

STACK 영역은 데이터가 높은 주소에서부터 낮은 주소로 향하는 방향성을

HEAP 영역은 낮은 주소에서 높은 주소로 향하는 방향성을 가지고 있다. 

 

DATA 영역은 프로그램이 실행되고 끝이 날 때까지 데이터를 유지하는 전역변수와, 정적변수를 담아두는 영역이다.

이 영역은 전역변수의 초기값의 유무에 따라 BSS, DATA로 또 나눠진다.

초기값이 존재하지 않는 BSS는 0으로 초기화된다.

 

CODE 영역에는 프로그램의 소스 코드가 올라간다.

 

위의  이미지 파일에서는 변수 초기 데이터상수값 데이터

DATA 영역과 CODE 영역에 겹쳐 모호하게 그려져 있다.

 

그 이유는

DATA 영역의 정적변수 중 

오직 읽기만 가능한(read-only) const string, const 전역변수들은

CODE 영역에서도 존재할 수 있기 때문이다.

 

컴퓨터의 메모리 영역을 간략히 알아보았다.

 

 

 

Heap 설명

 

 

 

이 글의 주요 주제인 Heap에 대하여 설명하겠다.

 

메모리 영역을 설명하면서도 거론되었지만

Heap은 프로그램이 실행되는 시점에 (runtime) 메모리를 할당하기 위한 영역이다.

 

 

 

Heap의 장점

 

 

 

Heap의 장점에는 보통 3가지로 이야기할 수 있는데

 

Lifecycle(생명주기)

Large size

Dynamic allocation 

 

이렇게 3가지가 있다.

 

Heap 영역의 장점을 설명하기 앞서

Stack 영역의 문제점에 무엇이 있는지 적겠다.

 

 

Stack 영역은 보통 1MB라는 상대적으로 적은 크기의 범위와 짧은 수명주기를 가진다.

Stack 영역에서의 데이터들의 수명주기가 frame 단위로 있어

데이터가 존재하는 함수가 호출되고 반환된다면 그 데이터도 같이 사라진다.

 

그렇다면 Heap 영역은 어떻게 이러한 단점을 극복하는 장점을 가지느냐.

 

 

 

LIfecycle : 

Heap 영역에 생성된 데이터는 그 생명주기가 Stack처럼 프레임 단위가 아니라

사용자(프로그래머)가 할당을 해제해주기 전까지 그 데이터가 유지된다.

 

 

Large size :

Stack은 상대적으로 적은 용량을 가지고 있는데 Heap 상대적으로 더 넓은 범위를 가지고 있다.

 

 

Dynamic allocation :

Heap 영역은 다른 메모리 영역과는 다르게 runtime 시에 메모리를 할당하기 위해

만들어져 있다. 사용자의 의도에 맞게 runtime 중 메모리를 할당하고 해제할 수 있다.

 

 

Heap 영역이 사용되는 방법으로는 

 

수 백 KB, MB에 달하는 큰 용량의 데이터들 Stack이 아닌 Heap에 놓고

Heap 에 놓인 데이터의 주소만을 Stack에서 관리함으로 

사용자의 의도에 맞는 Lifecycle과 Large size 를 다 챙길 수 있다.

 

 

 

Heap 영역의 문제점

 

 

 

Heap 영역에 할당하고 해제하는데 꽤 자원소비가 심한 편이다.

 

할당 후 해제를 까먹Memory leak(메모리 누수)이 일어날 수 있다.

 

Heap 영역에서는 데이터들이 듬성듬성 배치되는데 그에 따라 

Memory Fragmentation(메모리 단편화)이 일어날 수 있다.

(Stack영역은 이름에서 느낄 수 있듯 차곡차곡 데이터들을 쌓는다.)

 

 

 

문제 해결 방안

 

 

다음과 같은 문제들의 해결방안으로는

 

 

첫 번째 문제 같은 경우는 Heap 영역의 특성으로 어쩔 수 없는 부분이다.

속도 같이 performance가 중시되는 경우엔 cache hit을 높인다거나 다른 방안을 모색하여보자.

 

 

Memory leak(메모리 누수)이란

사용자 메모리를 사용한 후 해제를 하지 않아 사용되지 않는 데이터가 메모리에 남아있는 것이다.

Heap 영역에서 이러한 문제를 방지하기 위해선

메모리를 직접 관리해주는 언어를 사용하거나 c++ 같은 경우 스마트 포인터 같은

함수를 사용하여 Memory leak을 방지할 수 있다. 역시 Heap 영역을 다룰 땐 사용자의 집중이 필요하다.

 

 

Memory Fragmentation(메모리 단편화)이란

메모리에서 데이터들이 듬성듬성 할당되어 있다 보니 남아있는 부분을 합하면 충분히 새로운 데이터를 할당할 수 있지만 실제로는 데이터들이 듬성듬성 할당된 채로 할당되고 해제되어 새로운 데이터를 할당하기에 마땅한 빈자리가 존재하지 않게 된다.

ex) 4인에서 포장마차에 갔는데 4인석의 원형 테이블이 3개 있고 모든 테이블다른 손님들이 2자리씩 차지를 하고 있다.

전체 좌석 12(4 * 3), 현재 차지 중인 좌석 6(3 * 2)로 충분히 우리의 일행 4인이 들어갈 수 있지만 ; 12 >= 6 + 4

4인이 한 테이블을 사용하기엔 불가능하다!

이러한 개념의 memory fragmentation은 Internal Fragmentation(내부 단편화), External Fragmentation(외부 단편화)로 나뉜다.

 

 

Internal Fragmentation : 

메모리가 할당될 때 프로그램에서 사용되는 메모리 양을 초과하는 메모리를 할당 받았을 때 일어나는 현상이다.

 

External Fragmentation :

Heap 영역 특성상 메모리가 할당되고 해제의 반복 속에 작은 메모리들이 중간중간 존재하게 된다. 이러한 사용하지 않는 메모리에 의해 총 메모리 공간은 충분하지 못하여 할당이 불가능한 현상이다.

 

 

이러한 Memory Fragmentation의 해결 방법으로는

Paging 기법, Segmentation 기법, Memory pool 기법이 있다.

Paging 기법은 외부 단편화를 막기 위해 쓰이고

Segmentation 기법은 내부 단편화를 막기 위해 사용된다.

두 기법은 모두 보조기억장치를 빌려 사용하는 가상메모리를 사용한다

 

 

Paging 기법 :

Page 자체는 가상메모리를 같은 크기의 블록으로 나눈 것을 의미하는데 

메모리를 page 단위로 나눈 것frame이라 한다. 이때 page와 frame은 같은 크기를 가진다.

그렇기에 둘 사이에서는 데이터 이동이 있어도 문제가 없다.

Paging 기법은 이러한 특성을 이용해 사용하지 않는 frame page로 사용할 데이터 page에서

frame으로 옮겨 사용하는 기법이다. 이 기법이 사용되기 위해선 paging table을 만들어 page와 frame을

mapping 해줘야 한다. 이 기법의 문제점이라고는 frame, page 모두 일정한 크기를 가지기에 그 크기의

맞지 않은 데이터가 들어온다면  빈 공간이 생겨 내부 단편화가 생길 수 있다.

 

 

Segmentaion 기법 : 

Paging 기법과 다르게 Segmentaion 기법은 가상메모리를 서로 다른 크기의 블록으로 나눠 사용한다.

이 때 이 블록을 Segment라고 한다. 각 segment 들은 서로 다른 크기이며 연속적인 공간에 저장되기에

내부 단편화 문제를 해결한다. 이 기법 또한 가상메모리를 사용하기에 mapping을 위한 table이 필요한다.

 

 

Memory pool 기법 :

이 기법은 식당에서 자리를 예약하듯 프로그램 실행에 있어 필요한 메모리 공간을 사용자가 직접 지정하여

할당을 받아 놓은 다음 사용하고 반납하는 기법이다. 이렇게 봐서는 유연한 Stack처럼도 들릴 수도 있다.

이 기법에서는 모든 게 딱 필요한 만큼 만들어지고 사라지기에 Fragmentaion 문제가 발생하진 않으

Memory pool을 위해 할당된 메모리는 사용하지 않을 때에도 존재하기에 그 자체로 Memory leak인 방식이다.

그러니 Memory pool의 크기가 Fragmentation의 크기보다 크다면 사용을 지양하는 것이 현명하다.

 

 

 

이렇게 간략하게 메모리의 영역 구조와 Heap의 의미, 목적, 문제점, 해결방안을 알아보았습니다.

 

 

 

Heap 영역을 사용함에 있어서 요즘 나오는 언어들은 언어 자체에서 메모리를 관리하는 언어가 있어

직접 할당, 해제하는 일은 드물지만

관리를 지원하지 않는 언어에서는 사용자(프로그래머) 본인이 할당, 해제를 신경 써서 해줘야 합니다.

 

 

읽어주셔 감사합니다.

 

 

 

 

 

 

본 글을 작성함에 있어 아래 글을 참조하였습니다.

 

https://jeong-pro.tistory.com/91

댓글