본문 바로가기

프로그래밍/C

[C] 컴퓨터의 산와머니, 동적 할당 (Ver. c) (개념편)

들어가며

들어가기에 앞서 본 필자는

대부업에 관해서는 잘 모르고

대출과 금융권에 대해서 심도 있는

소견을 가진 사람이 아니니 이점 참고하며

글을 읽어나가길 부탁하겠다.

 

전 포스트에서는 메모리에 대해서 알아보았다.

그중에서도 함수의 호출과 관련이 있는,

아무튼 프로그램이 실행되는 것과 아주 밀접하게

관련이 있는 '스택 영역(Stack Segment)'에 대해서 알아보았다.

 

오늘은 메모리의 여러 영역 중에서도

사용자가 직접적으로 관여하여 관리할 수 있는,

그리고 해야만 하는 영역인

'힙 영역(Heap Segment)'에 대해서 알아볼 예정이다.

 

메모리계의 산와머니, 동적 할당

'힙 영역(Heap Segment)'의 메모리 크기

프로그램이 실행되는 도중인 런 타임(Run Time)

사용자가 직접 결정하게 된다.

이렇게 사용자가 지맘대로 메모리를 대출받는 것

메모리의 동적 할당(Dynamic Allocation)이라고 한다.

말 그대로 유동적이게 메모리를 할당받아서 동적 할당이라고 하는 것이다.

 

murloc? malloc?

그럼 어떻게 사용자의 임의대로 메모리를 할당받을 수 있을까.

'memory allocate', 직역하자면 '메모리 할당'.

 통칭 'malloc()' 이라는 함수를 사용하여 할당받을 수 있다.

malloc() 함수는 프로그램이 실행 중일 때,

사용자가 직접 힙 영역에 쳐들어가서

메모리를 할당할 수 있도록 협박해준다.

 

이런 어마 무시한 malloc() 함수의 원형은 다음과 같다.

참고로, 메모리 할당과 해제 함수는 stdlib.h 헤더 파일에 선언되어 있다.

#include <stdlib.h>
void* malloc(size_t size);

 

다시 한번 말하지만 '함수'의 원형이다. 헷갈리지 말길 바란다.

위 코드에서 괄호 안에 있는 것은 당연하게도 매개 변수 선언이다.

이때 'size_t' 타입(자료형)은 부호가 없는 정수,

즉 '절댓값' 정도로 이해하면 된다.

 

malloc() 함수는 인수로 할당받고자 하는 메모리의 크기

'바이트(Byte)' 단위로 전달받는다.

아무튼 함수를 실행시키면 일수 땡기러 가는 깍두기 형님들마냥

살벌하게 사용자의 주문에 맞는 아직 할당되지 않은

적당한 크기의 메모리 블럭을 물색한다.

이렇게 적절한 블럭을 발견하면

찾은 블럭의 첫 번째 바이트의 주솟값을 반환한다.

복도식 아파트에 비유하자면 그 층의 첫 번째 가구, 즉 'X01호'를 가리킨다는 소리다.

 

그런데 힙 영역에 할당할 수 있는 적당한 블럭이 없을 경우에는?

아무 수확도 없으니 당연하게도 '널(NULL)'을 반환한다.

따라서 여기서의 'NULL'의 의미'존재하지 않는 메모리 주소'이다.

 

눈치챈 독자들도 있을 것이다.

malloc() 함수를 실행시키고, 성공과 실패 둘 다 주솟값을 반환하지 않는가?

그렇다면 그 할당받은 메모리 공간을 누구에게 부여해야 하는가?

라는 의문을 합리적으로 가질 수밖에 없다.

그렇다.

당연하게도 힙 영역에 할당된 메모리 공간으로 접근하려면 포인터를 사용해야 한다.

 

세 줄 요약하자면 다음과 같다.

그림 9 - malloc() 함수 세 줄 요약

 

과도한 빚은 당신에게 큰 불행을 초래할 수 있습니다.

그림 10 - 콩과 팥, 기타등등 견과류

저 듬직하게 우리를 뒷받침해줄 것 같은 신뢰의 표정을 보라.

믿음직한 제3금융권에서 든든하게 메모리 공간을 대출받았고

필요한 곳에다가 적절하게도 썼으니 이제 상환해야 하지 않겠는가?

근데 막상 빌리기만 했지 돌려주는 방법을 모른다.

그렇기에 우린 아직 빚이라는 족쇄에 구속되어 있는 처지라고 할 수 있다.

그럼 어떻게 그 연옥의 굴레에서 벗어날 수 있을까.

 

우린 노예가 되지 않는다!

누군가, 비장한 표정으로 말했다.

그림 11 - 그롬마쉬 헬스크림

그리고 우리 또한 어떠한 사유로든 간에 노예가 되어서는 안 된다.

그러니까 제때제때 빚을 갚고 착실히 살아가도록 하자.

혹시 빌린 돈이 있지만 스쿠버다이빙을 거하게 조진 독자라면,

······, 할 말이 많지만 하지 않겠다.

 

아무튼 우리는 그런 경제적 제약으로부터 자유로워질 필요가 있다

그렇기에 'free()' 함수를 통해서 우린 비소로 자유로워질 수 있다.

'free()' 함수는 힙 영역에서 할당받은 메모리 공간

원래의 주인, 큰 형님 운영체제로 반환해 주는 함수다.

 

동적 할당으로 힙 영역에 생성되는 메모리의 크기

런 타임 내내 변화한다.

따라서 free() 함수를 사용하여 다 사용한 메모리를

상환(해제) 하지 않으면?

그림 12 - 콩팥과 기타 장기자랑

다음 생에는 그러지 말길 바랄 뿐이다.

운영체제도 나름의 사정이 있는 지라,

메모리가 부족해지는 현상이 발생할 수도 있기 마련이다.

이처럼 사용이 끝난 메모리를 해제하지 않아서 메모리가 부족해지는 현상,

이를 '메모리 누수(Memory Leak)'이라고 한다.

 

그럼 우리는 자유로움에 대한 본질을 알지 않으면 안 된다.

따라서 free() 함수의 원형은 다음과 같다.

#include <stdlib.h>
void free(void* _Block);

 

free() 함수는 인수를 통해서 해제하고자 하는

메모리 공간을 가리키는 포인터를 전달받는다.

인수의 타입이 void형 포인터로 선언되어 있다.

이는 어떠한 타입의 포인터라도 가리지 않고

인수로 전달해버리겠다는 우리의 대출 상환의 의지다.

혹은 뭐든 가리지 않고 우리의 소중하고 중요한 것들 중에서

돈을 제외한 무언가를 가져가 버리겠다는 암묵의 협박일 수도 있다.

 

무슨역전세계

그림 13 - 의문을 가지는 독자

'잠깐 필자 양반, 동적 할당이 있는데 그럼 정적 할당이라는 건 없가벼?'

좋은 질문이다.

하지만 재미있는 사실은

이미 독자 여러분들이 그것이 무엇인지

그리고 그것을 어떻게 하는지 알고 있다.

다만 그게 정적 할당이라는 인지가 없어서 그런 것 뿐이다.

다음의 코드를 보라.

int num;

 

즉, 선언하면서 크기를 지정하여 해당 크기만큼의 메모리를 할당하는 것.

이것이 바로 '정적 할당'이다.

int형의 4바이트만큼의 크기를

사전에 할당받겠다는 의미의 선언이다.

즉, 변수 선언의 방법이 정적 할당이라고 봐도 무방하다.

 

그리고 여담으로,

동적 할당사용자가 해제하기 전까지 계속 유효한데 반해

정적 할당효력 지역을 벗어나면 소멸하게 된다.

이는 메모리에서 지워짐을 의미한다.

 

마치며

오늘은 제3금융권, 대부업에 대해서 알아보았다.

어떠한가.

귀여운 견과류 친구들과 함께 신나는 공부를 한 소감이?

간담이 서늘해지도록 머릿속에 잘 들어오지 않던가?

아무튼 개념적인 부분은 여기까지 소개하고

다음 글은 동적 할당의 활용에 대해서 알아보도록 하자.

또 올 테니 긴장하라.


참고 및 출처

코딩의 시작, TCP School

코딩 도장