코가손의 블로그
컴파일 과정 본문
소스 코드는 아래의 그림과 같은 과정을 거쳐 실행 파일(.exe)로 만들어 진다.
전처리기(preprocessor) : 소스 코드의 주석 제거, define을 치환하는 단계
컴파일러(compiler) : 어셈블리 파일로 변환, 어셈블리코드는 CPU 명령어 조합이며 어셈블리어는 CPU에 의존적임
어셈블러(assembler) : 오브젝트 코드 파일로 변환, 오브젝트 코드는 0과 1로 이루어진 코드이다. 주소 정보는 아직 확정되지 않은 상태이다.
링커(linker) : 오브젝트 파일들을 묶어서 실행 코드 파일로 변환한다. 운영체제가 로딩할 수 있도록 주소 정보를 할당한 파일을 만들어 낸다. 그래서 링커는 운영체제에 의존적이다.
전처리 과정
전처리기는 헤더 파일들과 메크로를 치환하여 프로그램에 적용한다. 전처리기가 #include 문장을 만나면
해당 헤더 파일을 찾아서 그 파일의 내용을 삽입한다. #define이나 #ifdef와 같은 매크로는 심볼 테이블(symbol table)
에 저장한 뒤, 심볼 테이블에 있는 문자열과 같은 문자열을 소스코드에서 만나면 매크로를 치환한다.
컴파일 과정
컴파일러가 하는 역할은 front-end, middle-end, back-end 로 나누어 볼 수 있다.
front-end, 에서는 프로그래밍 언어를 처리한다. 이 단계에서 소스 코드가 문법에 맞게 작성되었는지 분석한다.
어휘 분석, 구문 분석, 의미 분석, 중간 코드 생성을 한다.
어휘 분석(lexical analysis) : 소스 코드를 의미 있는 최소 단위 토큰으로 나눈다.
구문 분석(syntax analysis) : 토큰으로 parse tree를 생성하여 문법 오류를 검출한다.
의미 분석(semantic analysis) : parse tree를 이용해 의미상 오류가 있는지 검사한다. (의미상 요류-> 함수의 매개변수, 변수의 자료형, 값을 0으로 나누는지, 정수와 문자열을 더하는지 등)
중간 코드 생성(code generation) : 트리 형태의 중간 표현 GIMPLE tree를 생성한다.
middle-end 에서는 최적화를 수행한다.
back-end 에서도 최적화가 이루어지며 어셈블리 코드를 생성한다.
컴파일 과정
어셈블리 코드를 기계어(0, 1)로 변환한다. 생성되는 목적 파일은 바이너리 포맷 구조를 갖는다.
링킹 과정
어셈블러에 의해 생성된 목적 파일들과 이 프로그램에서 사용된 라이브러리들을 연결시키는 작업을 한다.
이 과정에서 printf()와 같은 함수에 대한 라이브러리가 연결된다.
'C++ > 문법' 카테고리의 다른 글
C++ 객체 생성 (0) | 2021.11.11 |
---|---|
C++ 정적 바인딩 vs 동적 바인딩 (0) | 2021.11.11 |
C++ 깊은 복사 vs 얕은 복사 (0) | 2021.11.11 |
C++ static, extern (0) | 2021.11.09 |
C++ 포인터 & 참조 (0) | 2021.11.09 |