KH_C++
가비지 컬렉션, 메모리 단편화, 메모리 풀, 댕글링 포인터 본문
[ 가비지 컬렉션(Garbage Collection) ]
Garbage Collection, 줄여서 약어로 GC라고도 부른다. 영어로 그대로 읽어서 가비지 컬렉션이라고 부른다. 메모리 관리 방법 중에 하나로, 시스템에서 더 이상 사용하지 않는 동적 할당된 메모리 블록을 찾아 자동으로 다시 사용 가능한 자원으로 회수하는 것으로 시스템에서 가비지 컬렉션을 수행하는 부분을 가비지 컬렉터라 부른다.
C언어는 프로그래머가 메모리를 할당한 뒤 수동으로 해제까지 직접 해 줘야 한다. 그래서 메모리를 할당해 놓고 필요 없어진 뒤에도 해제를 안 하는 일 등이 생겨서 메모리 누수가 생기거나 거꾸로 해제했던 메모리를 다시 사용하거나 하는 실수 등에 버그가 양산된다.
이러한 문제들을 해결하기 위해서 제시된 것이 가비지 컬렉션이다. 이 가비지 컬렉션 기능을 채택한 언어의 경우에는 이 가비지 컬렉션에서 제공하는 할당과 해제를 이용하여 자동으로 프로그램이 실행되며 생기는 쓸모없어지는 메모리들을 알아서 수집하고 관리해준다.
[ 메모리 단편화 ]
RAM에서 메모리의 공간이 작은 조각으로 나뉘어져 사용 가능한 메모리가 충분히 존재하지만 할당(사용)이 불가능한 상태를 보고 메모리 단편화가 발생했다고 한다.
메모리 단편화는 내부 단편화와 외부 단편화로 구분 가능하다.
내부 단편화(Internal Fragmentation)
메모리를 할당할 때 프로세스가 필요한 양보다 더 큰 메모리가 할당되어서 프로세스에서 사용하는 메모리 공간이 낭비되는 상황
ex) 메모장을 켰는데 OS가 4KB를 할당해줬다. 그런데 사실상 1kb만큼만 사용하고 있을 때 필요 이상으로 프로세스가 메모리를 할당받았으므로 내부 단편화가 3KB만큼 생긴 것이다.
외부 단편화(External Fragmentation)
메모리가 할당되고 해제되는 작업이 반복될 때 작은 메모리가 중간중간 존재하게 된다. 이때 중간중간에 생긴 사용하지 않는 메모리가 많이 존재해서 총 메모리 공간은 충분하지만 실제로 할당할 수 없는 상황
ex) 메모리 처음 주소에 8MB짜리 프로세스가 할당되었고 바로 이어서 16MB짜리 프로세스가 할당되었다고 가정했을 때 8MB짜리 프로세스를 종료시키면 메모리 처음 주소부터 8MB만큼 공간이 생긴다.
이런 식으로 계속해서 빈 메모리가 쌓이는데 예를 들어서 빈 메모리의 공간중에 제일 큰 빈 메모리가 8MB라고 한다면 9MB짜리 프로세스를 할당을 해야 할 때 마땅한 공간은 없지만 전체적으로 메모리 여유는 있을 때 외부 단편화가 생겼다고 한다.
메모리 파편화 문제 해결 방법
1. 페이징(Paging)기법 - 가상 메모리 사용, 외부 단편화 해결, 내부 단편화 존재
2. 세그멘테이션(Segmentation)기법 - 가상 메모리 사용, 내부 단편화 해결, 외부 단편화 존재
3. 메모리 풀(Memory Pool) - 필요한 메모리 공간을 필요한 크기, 개수 만큼 사용자가 직접 지정하여 미리 할당받아 놓고 필요할 때마다 사용하고 반납하는 기법
[ 메모리 풀 (Memory Pool) ]
사용할 큰 메모리를 미리 할당하고 이를 작은 메모리 블록으로 나누어, 메모리가 필요할 때마다 이 블록을 건네주고, 다 사용한 블록은 돌려받는 기법.
직접 구현하거나 apr_pool, boost::pool 과 같은 라이브러리를 통해 사용할 수 있다.
다음과 같은 장점이 있다.
- 잦은 할당/해제시 발생하는 비용을 줄여준다
- 메모리 할당 시 실제로 몇 바이트를 할당 했는지 추가적으로 기록하는데, 이러한 메모리 사용을 줄여준다
- 메모리 단편화 문제 해결
[ 메모리풀의 한계 ]
- 미리 할당해놓고 사용하지 않는 순간에도 계속 할당해놓으므로 메모리누수가 있는 방식입니다.
- 메모리 사용 효율성이 떨어질 수 있습니다.
미리 상대적으로 큰 메모리를 할당하여 사용하기 때문에 사용하지 않는 부분이 미사용 메모리로 남게 됩니다. 물론 최근 하드웨어의 메모리 크기가 커진 관계로 심하게 큰 메모리를 미리 할당 하지 않는 이상 크게 신경쓸 정도는 아닙니다.
출처:
https://velog.io/@sweet_sumin/%EB%A9%94%EB%AA%A8%EB%A6%AC%ED%92%80
[ 댕글링 포인터 ( Dangling Pointer ]
해제된 메모리 영역을 가리키고 있는 포인터를 댕글링 포인터(Dangling Pointer, 허상 포인터)라고 한다. 동적 할당 된 포인터를 delete 하면 메모리 영역은 해제되지만 포인터는 삭제되지 않고 계속 남아있는 것이다.
이러한 댕글링 포인터가 가리키고 있는 메모리는 더이상 유효하지 않음으로 Premature free란 의미인
너무 급한 해제 또는 조숙한 해제라고 하기도 한다.
메모리 해제 한 뒤에 해제된 메모리에 접근하거나 함수 호출에서 자동변수를 가리키는 포인터를 반환하기에
아래의 결과가 나타나게 된다.
|
1
2
3
4
5
6
7
8
9
10
11
12
13
|
#include <stdio.h>
int main(){
bool a = true;
int *point;
if(a){
int dang=5;
point = &dang;
}
//point는 댕글링 포인터가 된다. 이유는 괄호안의 dang이 괄호를 벗어나면서 지역변수임으로
//할당된 스택영역이 제거되기 때문이다.
return 0;
}
|
문제점
- 메모리 접근시 예측 불가능한 동작을 일으킬 수 있다.
- 메모리 접근 불가 시 Segmentation fault 가 발생한다.
- 잠재적인 보안 위험이 있을 수 있다.
- 메모리 해제 후, 해제된 메모리에 접근할 때
- 함수 호출에서 자동 변수를 가리키는 포인터를 반환할 때
댕글링 포인터 발생 예방
- 메모리 해제 후에는 포인터를 NULL로
- free 함수를 대체할 새로운 함수를 생성
- 몇몇 럼타임 시스템이나 디버깅 시스템은 해제된 메모리를 특별한 값으로 덮어쓴다.
출처:
https://love-every-moment.tistory.com/44
'공부' 카테고리의 다른 글
함수 포인터 (0) | 2023.05.25 |
---|---|
Yaw Pitch Roll(요, 피치, 롤), Gimbal Lock(짐벌락), Quaternion(쿼터니언) (0) | 2023.05.17 |
동적할당, 동적할당해제, 스마트 포인터, 메모리 누수 (0) | 2023.05.04 |
DFS, BFS (0) | 2023.04.28 |
이진트리, 이진탐색트리, 전위, 중위, 후위 탐색 (0) | 2023.04.28 |