신입 게임 개발자의 프로그래밍 일기
[C++ 입문자에서 벗어나기]Chapter_2: 선언과 정의#3 본문
[C++ 입문자에서 벗어나기]Chapter_2: 선언과 정의#3
이번 포스팅은 선언에 대해서 이야기해보겠습니다.
선언은 "어떤 객체가 있음을 알림"이라고 선언과 정의#1 포스팅에서 말한 적이 있습니다.
이제 왜 그런지를 설명해드리겠습니다.
[빌드: 링커 단계]
빌드는 소스 파일(.cpp)들이 실행 바이너리(.exe, .so ...) 가공되는 과정이라고 생각하시면 됩니다.
왜 갑자기 빌드에 대한 이야기를 꺼냈느냐하면...
선언에 대해서 이야기할 때 빌드의 3단계들 중 링크 단계를 함께 설명하는 것이 보다 이해하기 용이하다고 판단해서입니다.
링크 단계는 빌드의 3단계 중 최종 단계로 컴파일(빌드 2단계)의 결과물들인 오브젝트 파일(.o)들을 적절히 연결해서 빌드의 최종 결과물인 실행 바이너리를 만들어내는 단계입니다.
적절히라는 말을 강조한데에는 이유가 있습니다.
링크의 주요 과정은 심볼 해석(Symbol Resolution)과 재배치(Relocation)으로 나뉘어지는데 이 중 선언과 정의는 심볼 해석과 연관이 있습니다.
[심볼 해석(Symbol Resolution)]
*심볼이란 변수나 함수를 뜻합니다.
심볼 해석이란, 링커 실행시 입력 받은 재배치 가능 목적 파일들내에 존재하는 심볼 참조들을 그것들 각각의 심볼 정의들에 연결시켜서 참조들을 해석하는 과정입니다.
간단한 소스파일과 objdump를 활용하여 설명하겠습니다.
먼저 main.cpp 소스와 main.o를 objdjump로 분석한 이미지입니다.
main.cpp는 다른 오브젝트 파일에 정의된 a라는 int형 변수의 값을 출력하라는 소스 파일입니다.
extern 키워드가 사용된 변수 선언은 컴파일러에게 해당 변수의 정의가 다른 오브젝트 파일에 있음을 컴파일러에게 알려줍니다.
컴파일러가 main.cpp를 컴파일하던 중 변수 a를 만날시 그것의 정의가 현재 모듈에 없으므로 다른 모듈에서 정의되어 있다고 가정하고 링커 심볼 테이블 엔트리를 생성하여 심볼 a에 대한 처리를 링커가 처리하도록 남겨둡니다.
main.o 파일을 조사해보면 SYMBOL TABLE에 *UND* 0000000000000000 a 형태로 저장되어 있음을 확인할 수 있습니다.
test.cpp는 더욱 간단합니다.
그냥 int a = 5; 라는 정의문만 있을 뿐입니다.
마찬가지로 objdump로 test.o파일을 분석해봤습니다.
SYMBOL TABLE에 data영역에 변수 a가 기록되어 있음을 확인할 수 있었습니다.
이제 g++에 -o 옵션을 줘서 main.o와 test.o를 링크 시켜서 실행파일 main.out을 생성 및 실행시켜보겠습니다.
5가 출력되는 것을 확인할 수 있습니다.
main.o에서의 a 심볼 참조가 test.o의 a 심볼 정의와 링크된 것입니다.
추가적으로 한가지 더 이야기하자면... 이 때 test.cpp의 a변수를 static으로 바꿀 경우, 링크가 불가능합니다.
그 이유는 static 전역 변수의 경우 해당 오브젝트 파일 내에서만 접근이 가능하도록 범위제한이 설정되기 때문입니다.
이번 포스팅을 끝으로 Chapter_2: 선언과 정의 파트를 끝마치겠습니다.
다음번 포스팅부터는 Chapter_3: 빌드에 대해서 이야기해보겠습니다.
'Language > C++' 카테고리의 다른 글
[C++ 입문자에서 벗어나기]Chapter_3: 빌드(Build)#2 (0) | 2017.12.01 |
---|---|
[C++ 입문자에서 벗어나기]Chapter_3: 빌드(Build)#1 (0) | 2017.11.14 |
[C++ 입문자에서 벗어나기]Chapter_2: 선언과 정의#2 (0) | 2017.11.08 |
[C++ 입문자에서 벗어나기]Chapter_2: 선언과 정의#1 (0) | 2017.11.05 |
[C++ 입문자에서 벗어나기]Chapter_1: 타입(Type)#3 (3) | 2017.11.03 |