C 코드에서 .exe 파일 실행까지

Ryan Ham·2024년 5월 15일
2

C++

목록 보기
1/26

Preprocessor

사람이 작성한 C코드는 먼저 컴파일되기 전에 proprocesor(전처리기)를 통해 전처리 과정을 겪게 된다. 코드에서 "#"부분에 관계된 cpp코드를 치환하는 역할을 하는데 대표적으로 #include로 불러오는 header file의 정보를 코드에 붙이는 일을 한다. 또한 compile과정에서 필요없는 코드의 주석을 제거하기도 한다.

Compiler

컴파일러는 크게 코드의 성능을 최적화하기 위해 코드를 일부 수정, 전처리된 코드를 컴파일하여 어셈블리어 코드로 변환하는 역할을 한다. 컴퓨터 언어를 나누는 기준 중 언어를 해석하는 방법이 interpret인지 compile인지로 나뉠만큼 중요한 부분이며, error 부분에서도 크게 compile-time error, runtime error가 존재한다.

아래의 예시는 cpp 코드가 compile과정을 통해 assembly code로 바뀌는 모습이다.


cpp

int main() {
    std::cout << "Hello World" << std::endl;
    return 0;
}

assembly

mov eax, 1
call std::cout << "Hello World"
ret

Assembler

Assembler는 compiler가 뱉은 assembly 코드를 받아서 object 코드를 생성한다. object코드는 우리가 예전에 즐겨봤던 매트릭스 영화화면에 등장하는 0과 1로 이루어진 기계어이다.

Linker

linker는 한개 이상의 object file들을 묶어서 최종적인 .exe file을 만드는 과정이다. 개별적인 파일을 검사하는 compiler과 달리 linker는 여러 object file들에 대한 전반적인 검사를 한다. 다음 예시는 compiler 단계에서는 문제 없이 통과하지만 linker 단계에서 에러가 나는 경우인데 이를 통해서 linker의 역할을 쉽게 이해해 볼 수 있다.


example.h

void myFunction(); // Function Prototype

main.cpp

#include "example.h"

int main(){
	myFunction();
}

cpp는 main에서 함수를 실행할때 실행 위치보다 먼저 함수가 정의되어 있어야 한다. 하지만 이렇게 되면 main 앞쪽부분이 너무 길어지므로 많은 경우에 main앞에 함수 prototype을 선언하거나 코드가 길어질 경우 따로 header 파일에 이를 정리한 후 #include로 함수를 가져와서 사용한다.

여기서, Compiler는 함수의 완전한 정의(몸통)까지 보지 않고 함수가 선언(prototype과 interchangable하게 단어를 사용)만 보고 통과시킨다. Linker 부분에서는 실제로 함수의 정의부분까지 찾아가서 링킹 역할을 하게 된다. 따라서 위의 예시처럼 함수의 prototype만 존재하고 몸통이 없는 경우는 compiler는 통과하지만 linker부분에서 에러가 나게 된다.

Loader

로더는 실제로 사용자들이 .exe file을 실행할때 OS에서 작동시키는 OS 구성요소이다. .exe file의 실행환경을 조성하고 stack, heap과 같은 memory를 준비한다.

profile
🏦KAIST EE | 🏦SNU AI(빅데이터 핀테크 전문가 과정) | 📙CryptoHipsters 저자

1개의 댓글

comment-user-thumbnail
2024년 5월 22일

유익해요!

답글 달기