본문 바로가기

C++

C++ 배우기 13(메모리 관리)

메모리 관리(memory management)

컴퓨터 메모리에 적용된 리소스 관리의 일종이다. 프로그램의 요청이 있을 때, 메모리의 일부를 해당 프로그램에게

할당하고, 더 이상 필요하지 않을 때 나중에 다시 사용할 수 있도록 할당을 해제하는 것이다.

 

그런데 C++ 프로그래밍을 배우면서 메모리 할당과 메모리 관리 부분에서 문제가 발생하기 쉽다고 한다.

그래서 좀 더 완벽한 프로그래밍을 위해서 메모리 관리의 내부 작동 방식들에 대해 이해하고 있으면 좋다고 한다.

 

오늘 알아볼것은 가비지 컬렉션, 메모리 누수, 메모리 단편화와 같은 메모리 관리 및 문제점들에 대해 조금

알아보고자 한다.


가비지 컬렉션(garbage collection)

쓰레기 수집이라고도 부르는 이것은 메모리 관리 기법들 중의 하나이며, 프로그램이 동적으로 할당했던

메모리 영역 중에 필요없게 된 영역을 해제하는 기능을 말한다.

 

가비지컬렉션은 동적 할당된 메모리 중에서 메모리가 부족해질 경우, 더 이상 사용할 수 없는 영역(어떠한 변수도 가리키지 않는 영역)을 자동으로 탐지하여 해제해주는 기법이다.

하지만 이러한 기능은 JAVA, C# 등에서는 기본으로 작동을 하지만, C와 C++에서는 기본적으로 가비지 컬렉팅 해주는

기능이 없다. 이는 최대한의 자유를 보장하기 위해 수동 메모리 관리를 바탕으로 만들어졌기 때문이라고 한다.

 

가비지 컬렉션이 지원이 된다면 프로그래머가 동적 할당한 메모리를 딱히 신경 쓰지 않아도 된다.

따라서 이미 해제된 메모리에 접근하거나, 이미 해제한 메모리를 또 해제하거나 또는 더 이상 필요하지 않은 메모리가

해제되지 않고 남아있는 메모리 누수같은 현상들을 막아주는 장점이 있다.

하지만 어떤 메모리를 해제해야 할지 결정하는 데에도 비용이 들고, 가비지 컬렉팅이 일어날 타이밍을 예측하기 힘들다는

단점도 있다. 이러한 이유 때문에 실시간으로 동작하는 시스템에는 적합하지 않다고 한다.

 

가비지 컬렉션에는 몇가지 작동 방식들이 있는데 추적 기반 쓰레기 수집참조 횟수 카운팅 기반 쓰레기 수집이 있다.

 

 

추적 기반 쓰레기 수집

Tracing Garbage Collection이라고 하며, 현재 가장 많이 사용되는 쓰레기 수집 기법 중 하나라고 한다.

현재 접근 가능한 메모리는 앞으로 사용할 수 있는 메모리로 간주하고, 그 외의 메모리들은 해제하는 방식이다.

이 추적 기반 쓰레기 수집에도 몇가지 다른 기법들로 세분화할 수 있다.

표시하고 쓸기(mark and sweep) 기법, 삼색 표시 기법, 객체 이동 기법, 세대별 쓰레기 수집 기법들이 있다.

 

 

참조 횟수 카운팅 기반 쓰레기 수집

일부 쓰레기 수집 기법들은 참조 횟수 계산 방식을 사용한다. 이는 해당 메모리를 얼마나 참조하는지 횟수를 기억해두고,

참조 횟수가 0이 되면 해당 메모리를 해제하는 방식을 말한다.

구현이 매우 간단하여서 C, C++, Python과 같은 소멸자를 구현할 수 있는 언어에서 종종 사용할 수도 있다고 한다.

 

 

JAVA와 C#과 같은 많은 컴퓨터 언어들이 가비지컬렉션 기법을 사용한다고 한다.

앞서 C, C++ 에는 가비지 컬렉션이 지원되지 않는다고 말했었지만, 직접 구현하거나 라이브러리를 통해 가비지컬렉션 기법을 사용할 수도 있다고 한다.


메모리 누수(memory leak)

컴퓨터 프로그램에서 필요하지 않은 메모리를 적절하게 제거하지 않아서 계속 점유하고 있는 현상을 말한다.

이러한 현상이 계속 지속되면서 누적되면 이런저런 버그들이 생기거나 심할 경우 프로그램이 다운되는 일이 일어난다.

그래서 이러한 문제를 방지하기 위해 위에서 봤던 가비지컬렉션 기능이 있긴 하지만, 완벽하게 방지되지는 않는다고 한다.

 

예를 들어 C++에서 동적 할당에 사용 가능한 new와 delete가 있다. new를 통해 할당해준 메모리를 제때 delete를 통해

해제하지 않아서 일어나는 것과 같은 메모리 누수 현상들을 주의해야 한다.

 

때문에 가비지 컬렉션을 지원하지 않는 프로그래밍 언어를 사용한다면, 메모리 누수가 발생하지 않도록 좀 더

주의 깊게 직접 메모리를 관리하는 것이 중요하다고 한다.


메모리 단편화(memory fragmentation)

메모리의 공간이 여러 개의 조각으로 나뉘는 현상을 말한다. 이러한 현상 때문에 사용 가능한 공간이 줄어들어

메모리가 충분히 존재하지만 할당이 불가능한 상태가 발생하거나, 읽고 쓰는 속도를 낮추는 문제점이 발생한다.

 

메모리 단편화도 몇 가지 종류로 나눌 수 있는데, 내부 단편화외부 단편화이다.

 

내부 단편화

메모리가 할당될 때 프로세스에 필요한 양보다 의도되지 않은 더 큰 메모리가 할당되어 쓰이지 않는 공간이 낭비되는

현상을 말한다.

 

 

외부 단편화

다양한 크기의 메모리가 할당되고 해제되는 것이 반복되면서 중간중간에 작은 메모리가 존재하는 것이 여러 조각을  나뉘는 현상을 말한다. 이로 인해 메모리 공간이 충분하지만 실제로는 할당되지 않는 상황이 발생할 수 있다.

 

 

이런 메모리 단편화 문제를 해결하는 페이징 기법세그멘테이션 기법, 메모리 풀의 방법이 있다.

 

1. 페이징 기법 (가상 메모리 사용, 외부 단편화 해결, 내부 단편화 존재)

사용하지 않는 프레임을 페이지에 옮겨, 필요한 메모리를 페이지 단위로 프레임에 옮기는 기법을 말한다.

페이지와 프레임을 대응시키기 위해서 page mapping 과정이 필요하여 paging table을 만든다.

페이징 기법을 사용하여 연속적이지 않은 공간도 활용할 수 있기 때문에 외부 단편화 문제를 해결할 수 있다고 한다.

하지만 페이지 단위에 딱 맞게 쓰는 게 아니라서 내부 단편화 문제는 여전히 존재한다.

 

2. 세그멘테이션 기법 (가상 메모리 사용, 내부 단편화 해결, 외부 단편화 존재)

가상 메모리를 서로 크기가 다른 논리적 단위 세그먼트로 분할해서 메모리에 할당한다. 세그먼트들은 연속적인 공간에

저장을 해놓고, 메모리에 적재될 때 빈 공간을 찾아 할당하는 기법이다.

프로세스에 필요한 메모리만 할당해주기 때문에 내부 단편화는 없지만, 프로세스가 메모리 해제를 하면서 생기는

외부 단편화 문제는 아직 있다.

 

 

3. 메모리 풀

필요한 메모리 공간을 필요한 크기, 개수만큼 사용자가 지정하여 미리 할당받고 필요할 때마다 사용하고 반납하는

기법이다.  C++에서 쓰이는 new와 delete 같은 기능이 있다.

미리 공간을 할당하여 사용하고 다시 반납하는 방식이기 때문에 외부 단편화가 발생하지 않는다.

또한 필요한 크기만큼만 할당하기 때문에 내부 단편화도 발생하지 않는다.

이는 잦은 메모리 할당과 해제가 필요한 경우에 사용하는 방식으로 프로그래머가 직접 구현해서 사용할 수 있는

방식이다.

하지만 미리 할당해놓고 사용하지 않는데도 계속 할당해놓고 있으면 위에서 봤던 메모리 누수가 발생하는 방식이다.


참고자료

https://kyoun.tistory.com/31

 

메모리 단편화 (페이징,세그멘테이션,메모리풀)

메모리 단편화 RAM에서 메모리의 공간이 작은 조각으로 나뉘어져 사용가능한 메모리가 충분히 존재하지만 할당(사용)이 불가능한 상태를 보고 메모리 단편화가 발생했다고 한다. 단편화의 종류

kyoun.tistory.com

https://gamedevlog.tistory.com/82

 

메모리 관리 3 - 메모리 단편화(Memory Fragmentation)

Goal 내부 단편화, 외부 단편화에 대해 설명할 수 있다. 메모리 단편화 해결 방법에 어떤 것들이 있는지 설명할 수 있다. 메모리 단편화(Memory Fragmentation)란? 메모리 단편화란 메모리 공간이 비효율

gamedevlog.tistory.com


출처: https://jeong-pro.tistory.com/91 [기본기를 쌓는 정아마추어 코딩블로그:티스토리]

https://junstar92.tistory.com/306

 

[C++] 메모리 관리 (1) - 동적 메모리, 배열과 포인터

References Professional C++ https://en.cppreference.com/w/ Contents 동적 메모리(Dynamic Memory) 다루기 배열과 포인터 비교 low-level 메모리 연산 C++은 C와 마찬가지로 최대한의 자유를 보장하며, 우리가..

junstar92.tistory.com

https://namu.wiki/w/%EC%93%B0%EB%A0%88%EA%B8%B0%20%EC%88%98%EC%A7%91

 

쓰레기 수집 - 나무위키

Tracing Garbage Collection. 가장 많이 사용되는 쓰레기 수집 기법으로 대부분 경우에 다른 수식어 없이 쓰레기 수집이라고 언급되면 이 방식을 말하는 것이다. 추적 기반이라는 이름답게 프로그램을

namu.wiki

 

https://ko.wikipedia.org/wiki/%EB%A9%94%EB%AA%A8%EB%A6%AC_%EA%B4%80%EB%A6%AC

 

메모리 관리 - 위키백과, 우리 모두의 백과사전

위키백과, 우리 모두의 백과사전.

ko.wikipedia.org