프로그래밍 언어/C++

C++ 컴파일 / 링크 프로세스의 작동 원리

Rateye 2021. 12. 4. 12:46
728x90
반응형
질문 : 컴파일 / 링크 프로세스는 어떻게 작동합니까?

컴파일 및 연결 프로세스는 어떻게 작동합니까?

(참고 : 이것은 Stack Overflow의 C ++ FAQ에 대한 항목입니다.이 양식으로 FAQ를 제공하는 아이디어를 비판하고 싶다면이 모든 것을 시작한 메타에 게시 할 수 있습니다. 이 질문은 FAQ 아이디어가 처음 시작된 C ++ 채팅룸 에서 모니터링되므로 아이디어를 제안한 사람들이 답변을 읽을 가능성이 큽니다.)

답변

C ++ 프로그램의 컴파일에는 세 단계가 포함됩니다.

  1. 전처리 : 전처리 기는 C ++ 소스 코드 파일을 가져와 #include , #define 및 기타 전 처리기 지시문을 처리합니다. 이 단계의 출력은 전 처리기 지시문이없는 "순수한"C ++ 파일입니다.
  2. 컴파일 : 컴파일러는 전 처리기의 출력을 가져 와서 객체 파일을 생성합니다.
  3. 연결 : 링커는 컴파일러가 생성 한 개체 파일을 가져와 라이브러리 또는 실행 파일을 생성합니다.

 

 

전처리 기는 #include#define 과 같은 전 처리기 지시문을 처리합니다. C ++의 구문과 무관하기 때문에주의해서 사용해야합니다.

#include 지시문을 각 파일의 내용 (일반적으로 선언)으로 #define #if 에 따라 텍스트의 다른 부분을 선택하여 한 번에 하나의 C ++ 소스 파일에서 작동합니다. #ifdef#ifndef 지시문.

전처리 기는 전처리 토큰 스트림에서 작동합니다. 매크로 대체는 토큰을 다른 토큰으로 대체하는 것으로 정의됩니다 (연산자 ## 는 의미가있을 때 두 토큰을 병합 할 수 있도록합니다).

이 모든 작업이 끝나면 전처리 기는 위에서 설명한 변환으로 인한 토큰 스트림 인 단일 출력을 생성합니다. 또한 각 줄이 어디에서 왔는지 컴파일러에 알려주는 몇 가지 특수 마커를 추가하여이를 사용하여 합리적인 오류 메시지를 생성 할 수 있습니다.

#if#error 지시문을 현명하게 사용하면이 단계에서 일부 오류가 발생할 수 있습니다.

컴파일 단계는 전 처리기의 각 출력에서 수행됩니다. 컴파일러는 순수 C ++ 소스 코드 (이제 전 처리기 지시문 없음)를 구문 분석하고이를 어셈블리 코드로 변환합니다. 그런 다음 해당 코드를 특정 형식 (ELF, COFF, a.out, ...)으로 실제 이진 파일을 생성하는 기계 코드로 어셈블하는 기본 백엔드 (도구 체인의 어셈블러)를 호출합니다. 이 개체 파일에는 입력에 정의 된 기호의 컴파일 된 코드 (이진 형식)가 포함되어 있습니다. 오브젝트 파일의 기호는 이름으로 참조됩니다.

개체 파일은 정의되지 않은 기호를 참조 할 수 있습니다. 선언을 사용하고 이에 대한 정의를 제공하지 않는 경우입니다. 컴파일러는 이것을 신경 쓰지 않으며 소스 코드가 잘 구성된 한 기꺼이 개체 파일을 생성합니다.

일반적으로 컴파일러를 사용하면이 시점에서 컴파일을 중지 할 수 있습니다. 이는 각 소스 코드 파일을 개별적으로 컴파일 할 수 있기 때문에 매우 유용합니다. 이것이 제공하는 장점은 단일 파일 만 변경하는 경우 모든 것을 다시 컴파일 할 필요가 없다는 것입니다.

생성 된 개체 파일은 나중에 쉽게 재사용 할 수 있도록 정적 라이브러리라는 특수 아카이브에 저장할 수 있습니다.

이 단계에서 구문 오류 또는 실패한 과부하 해결 오류와 같은 "일반적인"컴파일러 오류가보고됩니다.

링커는 컴파일러가 생성 한 개체 파일에서 최종 컴파일 출력을 생성합니다. 이 출력은 공유 (또는 동적) 라이브러리 (이름은 비슷하지만 앞서 언급 한 정적 라이브러리와 공통점이 많지 않음) 또는 실행 파일 일 수 있습니다.

정의되지 않은 기호에 대한 참조를 올바른 주소로 대체하여 모든 개체 파일을 연결합니다. 이러한 각 기호는 다른 개체 파일이나 라이브러리에서 정의 할 수 있습니다. 표준 라이브러리가 아닌 다른 라이브러리에 정의되어있는 경우 링커에 알려야합니다.

이 단계에서 가장 일반적인 오류는 정의 누락 또는 중복 정의입니다. 전자는 정의가 존재하지 않거나 (즉, 작성되지 않았거나) 해당 정의가 상주하는 개체 파일 또는 라이브러리가 링커에 제공되지 않았 음을 의미합니다. 후자는 분명합니다. 동일한 심볼이 두 개의 다른 개체 파일 또는 라이브러리에 정의되었습니다.

출처 : https://stackoverflow.com/questions/6264249/how-does-the-compilation-linking-process-work
728x90
반응형