0. 컴파일 과정

컴파일 과정은 전처리 -> 컴파일 -> 어셈블 -> 링킹 단계로 구분할 수 있다.

1. 전처리(Preprocessing)

// example.cpp
#include <iostream>
#include <vector>
#include "Example.h"

#define	SAFE_DELETE_ARRAY(p)	if(p)	{ delete[] p; p = nullptr; }

위와 같은 코드를 본 적이 있을 것이다.

#은 전처리 지시문을 의미하는 기호로, 전처리 과정에서 이 #이 붙은 구문들을 처리한다.

#include<iostream>, <vector>, "Example.h" 헤더 파일의 내용을 현재의 cpp 파일에 그대로 붙여 넣으라는 전처리문이다. 컴파일 하기 전에, 해당 cpp 파일에서 필요한 함수나 클래스 등의 선언부를 삽입하게 된다. 이 때, 헤더 파일에 헤더 가드가 없으면 중복 포함 문제가 발생할 수 있으니 #pragma once, #ifndef 등의 전처리문을 헤더에 잘 작성해주는 것이 중요하다.

#define은 매크로를 정의하는 전처리문이다. 매크로를 정의한 후, 함수와 같이 사용할 수 있다. #define VAR 3과 같이 상수를 정의할 수도 있는데, 상수의 경우 메모리 주소를 갖지 않기 때문에 디버깅할 때 불편할 수 있다.

2. 컴파일(Compile)

컴파일 과정은 Compiler가 고급언어를 어셈블리어로 변환하는 과정이다. 여기서 어셈블리어란, CPU 내의 register까지 조작이 가능한 low-level 언어이다.

컴파일러는 전처리 과정을 마친 코드들을 어셈블리어(ex. mov, call, ret 등)로 바꾸고, 변수와 함수 등의 이름을 심볼(Symbol)화 한다. 해당 심볼 정보를 심볼 테이블(Symbol Table)에 기록하는데, 심볼 테이블이란 변수나 함수 등의 symbol(이름)이 어떤 메모리 위치, 타입, 범위를 가지는지 기록한 데이터 구조이다. 심볼테이블에 기록되는 정보는 아래와 같다.

항목 예시
이름 g_value, main
타입 int, float(), char*
저장 위치 .data, .bss, .text
스코프 글로벌 / 로컬
정의 여부 선언만 됐는지 / 정의까지 됐는지(중복 정의 체크에 사용)

C++에서는 함수 오버로딩을 허용하므로, 함수 이름만으로는 중복을 구분할 수 없다. 따라서 컴파일러는 함수 이름과 인자 타입 정보를 조합한 고유한 심볼명을 생성한다. 이 과정을 네임 맹글링(name mangling)이라 한다.

3. 어셈블(Assemble)

Assembler가 컴파일 단계를 통해 어셈블리어로 되어있는 파일을 목적 코드(object code, 기계어이긴 하나 실행 가능한 형태는 아님)로 바꾸는 과정이다. 외부 파일에 정의된 심볼(ex. 다른 파일의 함수나 전역 변수)은 아직 기계어 주소를 모르므로, 해당 심볼 이름만 유지된 상태로 obj 파일에 기록된다.

4. 링킹(Linking)

Linker는 각 .obj파일에서 외부 심볼의 정의를 찾고 주소를 채워 넣어 완전한 실행 파일을 만든다. 정적 라이브러리(.lib)의 경우, 링커가 필요한 함수, 변수 등을 골라 실행파일(exe)에 직접 포함시킨다. 동적 라이브러리(.dll)는 링커가 파일 자체를 실행 파일에 포함하지 않고, 대신 심볼 참조만 포함한다. 이후 프로그램 실행 시, OS가 dll을 메모리에 로드하고 함수 주소 바인딩을 실시한다.

심볼의 주소를 채워 넣는 과정에서 여러 obj 파일의 심볼 테이블을 하나로 통합하는데, 중복된 심볼이 있을 경우 링커 에러(LNK 2005)가 발생한다.

예를 들어, Example.h 파일에 전역 변수 int g_value = 42;를 정의하고 이 헤더 파일을 여러 .cpp 파일에서 include 했다고 가정해보자. 전처리 과정에서 int g_value = 42; 코드가 각 cpp 파일마다 생겼을 것이다. 컴파일 과정에서는 각 파일의 심볼 테이블에 g_value에 대한 정보가 생겼을 것이고, 링킹 과정에 심볼 테이블을 통합하는 과정에서 링커 에러가 발생하게 된다. 이 때는, extern이 해결책이 될 수 있다.

Leave a comment