포인터는 C언어의 가장 큰 강점이자 우리를 늘 메모리 관련 문제로 괴롭히는 큰 위험요인이다. 많은 좋은 프로그램들이 C언어의 포인터 기교를 사용해서 엄청난 메모리 / 성능상의 이득을 얻었다. 몇년도 전이지만, 아직도 리눅스 커널과 리눅스의 tcp/ip 스택에서 C언어 포인터를 활용한 것을 처음 봤을때의 신선한 충격이 생생하다. 훌륭한 프로그래밍 언어들이 많이 나왔지만 여전히 C의 포인터만큼 HW 직관적이고 강력한 개념은 없는 것 같다. 그러나 동시에 포인터는 원인을 찾기 어려운 버그들을 만들어 내곤 한다. 특히 어떤 버그들은 원인을 찾고서도 고치기가 몹시 난해한 경우들도 있다. 이는 훌륭한 프로그램에서도 예외가 아니다. 모질라 재단은 파이어폭스의 메모리 누수 문제로 수 년간 씨름하다가 결국 C++로 개발된 기존 브라우저 엔진(Gecko)을 버리고, 아예 새로운 언어로 엔진(Servo)을 다시 개발하였다. 도요타 자동차는 급발진으로 수 많은 인명사고를 냈는데, 조사 결과 이 역시 C언어의 메모리 관리 문제와 연관되어 있었다. (이 사건으로 오늘날 대부분의 자동차 회사들은 괴상하고 재미없지만 C언어의 메모리 관리 문제를 회피할 수 있는 misra-C를 내부적으로 사용하고 있다.) C언어 메모리 문제들을 살펴보기 앞서 이번 포스트에서는 C언어의 메모리 구조와 C언어의 포인터로 인한 메모리 문제들의 유형들을 살펴볼 예정이다. 만약 C언어 메모리 문제들에 익숙하고 관리를 위한 테크닉들을 보고 싶으면 다음 포스트로 이동하자. 1.1 C언어 메모리 구조출처: https://www.geeksforgeeks.org/memory-layout-of-c-program/C언어 메모리 구조는 위 이미지와 같이 stack과 heap 그리고 static data 영역(initialized data)과 text 영역으로 구분된다. 각 영역은 다음과 같은 자료를 저장한다. 스택 (Stack)스택은 이름처럼 해당 영역에
메모리를 블록처럼 쌓아놓았다고 생각하면 쉽다. (자료구조에서 스택을 안다면 이해하기 편할 것이다.) 블록이 차곡차곡 쌓여 있기 때문에 중간의 블록을 빼는 것은 안된다. 중간에 있는 블록을 빼려면 마지막에 들어온 블록부터 빼내야 한다.
그림과 같이 스택에 할당된 메모리들은 함수 호출이 종료되면 해제된다. 따라서 프로그래머가 별도로 관리하지 않아도 된다. 스택은 x86_64 아키텍쳐 리눅스 PC에서 약 8Mb의 크기를 가진다. (스택의 기본 크기는 아키텍쳐에 따라 달라진다.) 만약 스택이 8Mb의 크기보다 많이 설정되면, 스택 오버플로우 문제가 발생한다. 힙 (Heap)힙은 '더미'로 직역된다. 스택이 함수 호출에 따라서 메모리가 차곡차곡 쌓인 모양으로 관리되는 반면, 힙은 이름 그대로 메모리가 힙 영역에 아무렇게나 할당되어 있다. 따라서 힙은 스택과 비교하면 크게는 다음 세가지 특징을 가지고 있다.
이와 같은 특징들로 인해서 힙은 스택과는 다른 종류의 메모리 문제를 발생시킨다.
보통 힙에 메모리 할당은 malloc, calloc, realloc 함수를 사용하고, 해제는 free 함수를 사용한다. 아래는 힙에 메모리를 할당하는 코드와 간단한 견본 이미지이다.
다음 포스트에서는 C언어 메모리 관리의 유형들에 대해 다룬다. (5/1 포스트 예정) www.kernelpanic.kr/33 만약 바로 C언어 메모리 관리 방법에 대해서 알고 싶다면 아래 포스트를 참조하자. (5월 초 포스트 예정) www.kernelpanic.kr/34 메모리 구조C 언어가 많은 사랑을 받는 이유는 바로 메모리가 아닐까 생각한다고 첫 시간에 이야기를 했었다. 오늘은 C 언어의 핵심 중 하나인 메모리 관리의 기본에 대해서 알아보도록 하겠다. 그 전에 먼저 메모리의 구조에 대해서 알아야하는데, 메모리 구조는 총 4개로 나뉘어 진다.
여기서 스택과 힙에 주목을 해볼 필요가 있다. 스택 영역컴파일 시점에 메모리가 결정되어 실행 속도가 빠르고 낭비가 없다는 특징이 있다. 하지만 스택 영역은 상대적으로 한계가 있기 때문에 스택 이상을 쓰게된다면 에러가 발생할 가능성이 존재한다. 힙 영역사용자가 직접 생성하는 혹은 할당하는 메모리 공간이다. Java 에서는 GC가 동작하여 활약하는 공간이라고 생각할 수 있다. 힙은 최적화를 할 때도 사용되며 스택보다 큰 데이터를 할당할 때도 사용되긴 하지만 사용자가 직접 만질 수 있는 공간이기 때문에 아무래도 힙 손상이 발생하기 쉽다. C 언어에서 메모리 사용하기c 언어에서 메모리를 조작할 때는 malloc과 free 를 이용하는게 일반적이다.
의 과정을 거치게 되는데, 좀 더 자세히 알아보자 malloc과 freemalloc과 free 와 같은 메모리 관련 함수는 stdlib.h 헤더에 존재하므로 malloc, free, memcpy, memset 을 사용하려면 해당 헤더를 include 해야 한다. malloc메모리를 할당받는 함수로 Memory + Allocation의 합성 약자로 메모리 공간을 확보하고 메모리 블록을 할당한다. malloc 함수를 사용할 때 매개변수로 size 를 지정하여 사용자가 얼만큼의 메모리를 할당받을 것인지 명시해야 한다. free앞에서 본 malloc 으로 메모리를 할당했다면 Heap 손상을 발생시키지 않기 위해서 메모리를 해제시켜야 한다. 만약 메모리 할당을 해제하지 않으면 후속 할당에서 에러를 발생시킬 수 있으므로 적절하게 메모리를 해제시켜야 한다.
메모리에 값을 저장하기앞선 코드에서는 메모리를 할당 하고 해제 하는 과정이었다. 이번에는 할당받은 메모리에 역참조를 이용하여 특정 값을 저장해보자. |