C 언어로 프로그램을 작성하다 보면 저수준의 메모리 구조에 대해 알아야하는 경우가 있습니다.
운영체제가 어떻게 메모리를 관리하는지 아는 것은 C 프로그래머가 기억하고 있어야할 어려운 부분중의 하나지요. 일반적으로 프로그램의 메모리는 텍스트, 데이터, BSS, 힙, 스택 등의 영역으로 나뉩니다. 이외에 운영체제가 관리하는 커널 공간이 존재합니다. 각 영역이 어떤 역할을 하는지 하나씩 알아보겠습니다.
(그림. Structure of Processes)
텍스트 세그먼트 (Text Segment)
텍스트 세그먼트는 보통 코드 영역이라고도 부르며, 실행할 프로그램의 명령어들이 저장되는 구역입니다. 즉, 우리가 작성한 C 소스 코드가 컴파일되어 기계어 형태로 이 영역에 올라가고, CPU가 이 명령어들을 차례대로 실행하게 됩니다. 이 영역은 일반적으로 읽기 전용으로 설정되어 프로그램이 실행 중에 자신의 코드를 임의로 변경하지 못하도록 보호됩니다. 비유하자면 텍스트 세그먼트는 프로그램의 '설계도' 또는 '레시피'와 같습니다. 한 번 작성된 요리 레시피는 요리하는 동안 바뀌지 않는 것처럼, 이 영역의 내용도 실행 중에는 그대로 유지되며 참고만 되는 것입니다.
데이터 세그먼트 (Data Segment)
데이터 세그먼트에는 프로그램의 전역 변수나 정적(static) 변수 중에서 초기값이 지정된 것들이 있습니다. 예를 들어 어떤 전역 변수가 5라는 값으로 초기화되어 있다면, 프로그램이 시작될 때 이 영역에 그 값 5가 이미 준비되어 있는 것입니다. 이러한 변수들은 프로그램이 실행되는 내내 메모리에 존재하며 모든 함수에서 접근할 수 있습니다. 비유하자면 데이터 세그먼트는 칠판의 특정한 위치에 적어둔 글자들과 같습니다. 프로그램이 시작할 때부터 전역 변수들이 일정한 초기값을 갖고 이 벽에 있으니, 필요한 상황에서 참조하면 됩니다.
BSS 세그먼트 (BSS Segment)
BSS 세그먼트는 전역 변수나 정적 변수 중에서 초기값이 주어지지 않은 것들이 차지하는 메모리 영역입니다. 이 영역의 변수들은 관례적으로 프로그램 시작 시 0으로 초기화됩니다. 예를 들어 초기값 없이 선언된 전역 배열이나 static
변수들은 이 BSS 영역에 공간만 할당된 채 시작하며, 값은 기본값(0)으로 채워지죠. BSS 세그먼트는 말하자면 벽지에 칠판에 아무 것도 적지 않은 공간과 같습니다. 아직 아무 것도 적지 않았지만 공간은 확보되어 있어서, 프로그램이 실행되면서 여기에 값들이 채워지게 됩니다.
힙 (Heap)
힙(Heap) 영역은 프로그래머가 직접 관리하는 동적 메모리 공간으로, 프로그램 실행 중 필요에 따라 메모리를 할당하고 해제할 수 있는 곳입니다. 예를 들어 실행 중 새로운 배열이나 객체가 필요하면 힙 영역에서 그만큼의 공간을 받아오며, 사용이 끝난 메모리는 다시 반환하여 힙에 돌려놓을 수 있습니다. 힙은 요청에 따라 크기가 커지거나 줄어들 수 있어 매우 유연하지만, 제대로 관리하지 않으면 메모리 누수와 같은 문제가 생길 수 있습니다. 비유하자면 힙은 창고에서 꺼내온 새 칠판과 같습니다. 프로그램은 창고에서 칠판을 꺼내서 쓰고 다 쓰면 다시 돌려놓아야 합니다.
스택 (Stack)
스택(Stack) 영역은 함수 호출 시 생성되는 지역 변수와 함수의 호출 정보(리턴 주소 등)가 저장되는 공간입니다. 함수를 호출할 때마다 스택에 새로운 스택 프레임(frame)이 추가로 쌓이고, 함수 실행이 끝나면 그 프레임이 제거되어 메모리가 자동으로 해제됩니다. 이름 그대로 스택은 쌓았다가 빼는 후입선출(LIFO) 구조로 동작하는데, 이는 마치 이동식 소형 칠판들을 쌓아두는 공간과 같습니다. 새로운 계산이나 작업이 필요할 때마다 위에 새 칠판을 올려두고 사용하다가, 작업이 끝나면 그 칠판을 치우는 것처럼 함수가 호출될 때마다 새로운 작업 공간이 생기고 함수가 끝나면 그 공간이 자동으로 정리됩니다. 너무 많은 칠판을 한꺼번에 쌓으면 무너질 수 있는 것처럼, 스택도 너무 많은 함수를 중첩해서 호출하면 스택 오버플로(stack overflow)라는 문제가 발생할 수 있습니다.
커널 공간 (Kernel Space)
커널 공간은 OS(운영체제)가 상주하는 보호된 메모리 영역으로, 시스템 리소스를 관리하는 핵심 코드와 데이터 구조, 장치 드라이버 등의 필수 구성 요소를 포함하고 있습니다. 이 영역은 일반 프로그램이 건드릴 수 없도록 격리되어 있으며, 오직 운영체제만이 접근할 수 있습니다. 쉽게 말해, 커널 공간은 프로그램 입장에서 '출입 금지' 구역이라고 할 수 있습니다. 이러한 구분 덕분에 사용자 프로그램이 실수로 잘못된 메모리를 접근하더라도 운영체제 자체는 보호되어 시스템의 안정성을 유지할 수 있습니다.
마치며
지금까지 텍스트 세그먼트부터 커널 공간까지 차례로 살펴보았습니다. 각 영역에는 저마다 역할이 있고, 이렇게 나누어 관리함으로써 프로그램의 효율성과 안정성이 높아집니다. 초보 개발자라도 이러한 메모리 레이아웃 개념을 이해하면, 오류가 발생했을 때 원인을 파악하거나 코드를 최적화하는 데 큰 도움이 될 것입니다.