1. C 파일이 실행 파일로 변환되는 과정
A. 전처리 : Preprocessor / cpp
전처리기 지시문을 처리합니다. 예를 들어, #include, #define 등이 처리됩니다.
## main.c (C 소스 파일) => main.i (전처리된 파일) $ gcc -E main.c -o main.i
B. 컴파일 : Compiler / cc1/cc1plus
전처리된 파일을 분석하여 어셈블리 코드로 변환합니다.
## main.i (전처리된 파일) => main.s (어셈블리 코드 파일) $ gcc -S main.i -o main.s
C. 어셈블리 : Assembler / as
어셈블리 코드를 더 잘개 쪼개서 기계어 인스트럭션 단위로 만들고, 이것들을 모아 목적 파일을 생성합니다.
## main.s (어셈블리 코드 파일) => main.o (목적 파일) $ gcc -c main.s -o main.o
D. 링크 : Linker / ld
여러 목적 파일과 라이브러리를 결합하여 실행 파일을 생성합니다.
## main.o (목적 파일) => main (실행 파일) $ gcc main.o -o main
2. 프로그램 실행
A. 실행파일 생성 (컴파일)
컴파일러는 소스 코드를 분석하여 각 종류의 데이터를 적절한 세그먼트로 분류
- Text 세그먼트 : 실행 가능한 기계어 코드를 텍스트 세그먼트로 분류
- Data 세그먼트 : 초기화된 전역 변수와 정적 변수
이 값들은 컴파일 시 이미 알려져 있고, 링크 과정에서 해당 세그먼트에 배치 - BSS 세그먼트: 초기화되지 않은 전역 변수와 정적 변수
초기화되지 않은 데이터를 위한 공간을 제공
링크 과정에서 해당 세그먼트에 배치되고 실제 메모리는 프로그램 로드 시 할당
B. 실행 파일 로드
운영 체제의 로더(Loader)가 실행 파일을 스토리지에서 메모리로 적재.
이때, 실행 파일의 헤더 정보를 읽어서 프로그램 실행에 필요한 메모리 구조를 파악
C. 메모리 영역(Segment) 생성 및 맵핑 ★ ★ ★ ★ ★
컴파일러와 링커에 의해 설정된 세그먼트 위치와 크기를 기반으로 실제 메모리 영역을 설정
실행파일에 정의된 대로 메모리에 로드
- Text (Read Only) : 실행 파일의 기계어 코드
- Data (R/W) : 초기화된 전역 변수 및 정적 변수
- BSS (R/W) : 초기화되지 않은 전역 변수 및 정적 변수. 실행 시 0으로 초기화
런타임에 결정
- Heap (R/W) : 동적 메모리 할당이 이루어지는 영역
프로그램 실행 중에 malloc, calloc, realloc 등의 함수로 메모리를 할당 - Stack (R/W) : 함수 호출 시 지역 변수 및 함수 호출 정보(리턴 주소, 매개변수, 지역 변수 등)를 저장, 호출 시 스택 프레임이 생성되고, 함수가 종료되면 스택 프레임이 해제
D. 실행
메모리에 적재된 후, CPU는 Text 세그먼트의 시작 주소에서 프로그램을 실행
- 프로그램 시작 : main 함수가 호출되면서 프로그램 실행이 시작
- 함수 호출 : 각 함수 호출 시 스택에 스택 프레임이 생성
스택 프레임에는 함수의 매개변수, 지역 변수, 리턴 주소가 포함 - 메모리 할당 : 동적 메모리 할당이 필요한 경우 힙에서 메모리를 할당
- 프로그램 종료 : main 함수가 종료되거나 exit 함수가 호출되면, 프로그램 실행이 종료되고 운영 체제는 메모리를 회수
3. 예제
#include <stdio.h>; #include <stdlib.h>; int global_var = 10; // Data 영역 void function() { int local_var = 20; // Stack 영역 printf("Local variable: %d\n", local_var); } int main() { static int static_var = 30; // Data 영역 int *heap_var = (int *)malloc(sizeof(int)); // Heap 영역 if (heap_var == NULL) { return 1; } *heap_var = 40; printf("Global variable: %d\n", global_var); printf("Static variable: %d\n", static_var); printf("Heap variable: %d\n", *heap_var); function(); free(heap_var); // Heap 메모리 해제 return 0; }
- global_var와 static_var는 Data 영역에 위치
- local_var는 Stack 영역에 위치
- heap_var는 Heap 영역에 위치
- function과 main 함수의 기계어 코드는 Text 영역에 위치