참고 문헌 : 씹어먹는 C++ - <20 - 3. 코드 부터 실행 파일 까지 - 링킹 (Linking)>
저장 방식 지정자 (Storage class specifier)
static
thread_local
extern
mutable
<- 저장 기간과 링크 방식에 영향xauto
<- c++11 부터 제거됨 (auto 키워드로 대체)register
<- c++17 부터 제거됨
저장 기간 (Storage duration)
- ___ 객체들에게만 해당
- 자동 저장 기간
- scope
{}
안에 정의 된 녀석들static
,extern
,thread_local
키워드 지정 제외
- 지역 변수
- scope
- static 저장 기간
- 프로그램 시작할 떄 할당, 끝날 때 소멸
- 함수 밖에 정의된 것들 (
전역변수
,namespace 단위
) static
orextern
정의 객체
- 쓰레드 저장 기간
- 쓰레드 시작할 떄 할당, 종료될 떄 소멸
- 각 쓰레드들이 해당 객체 복사본 가짐
thread_local
선언 객체
- 동적 저장 기간
- 동적 할당 함수를 통해 할당, 해제되는 객체 (
new
,delete
) - 링커에서 어디에 배치 할 지 중요 정보로 사용됨
- 동적 할당 함수를 통해 할당, 해제되는 객체 (
링크 방식(lINKAGE)
- 링크 방식 없음 (No linkage)
- 지역 함수들은
{}
안에 링크 방식이 없는 상태로 정의되어 있음
- 지역 함수들은
- 내부 링크 방식 (Internal Linkage)
static
으로 정의된 함수, 변수, 템플릿 함수, 템플릿 변수 등.- 같은 TU 안에서만 참조
- C#의
static
이 다른 파일에서 사용가능한 것과 달리, Cpp에서는 사용 불가.
- C#의
- 외부 링크 방식 (External Linkage)
- 외부 링크 방식으로 정의된 개체는 다른 TU에서도 참조 가능
- 언어 링크 방식 정의가 가능해, 다른 언어 사이에서 함수 공유 가능
- 전역 변수&함수,
extern
방식,
- 이름 맹글링 (Name Mangling)
- 목적 코드 생성 시에 함수 이름이 바뀜. (c의 경우, 그대로)
- 같은 이름의 함수 정의 가능 <- 맹글링하는 이유
- 함수 이름 자체만으로 어떤 함수 호출할 지, 구분 불가
C# & Java
에서리플렉션
이 가능한 이유 : 맹글링을 하지 않음.
extern
: 이름 맹글링을 하지 말라고 컴파일러에 전달
링킹
- 각각의 TU들에서 생성된 목적 코드들을 한데 모아서 하나의 실행 파일을 만듦
nm
프로그램을 사용하여, 목적 코드 확인가능- 대문자 알파벳 심볼 : 외부 링크 방식
- 소문자 알파벳 심볼 : 내부 링크 방식
b, b
: 초기화 되지 않은 데이터 섹션 (BSS 섹션)D, d
: 초기화 된 데이터 섹션T, t
: 텍스트 (코드) 섹션R, r
: 읽기 전용 (read only) 섹션
- 목적 코드들은 링킹 전 까지 심볼 위치 확정 x
- 재배치 (Reloaction)
- 재배치 테이블(Relocation Table)
- 심볼 위치 확정이 되면 값을 바꿔야 할 부분을 적어놓은 테이블
- R_X86_64_PC32
- 상대 오프셋 재배치 유형
- 정적,동적 링크 모두에서 사용 (특정 상황에서 동적 링크는 안될 수 있음)
4바이트 영역을 S + A - P 를 계산한 값을 치환하라
S
: 재배치 후에 해당 심볼 실제 위치P
: 재배치 해야하는 부분 위치A
: 더해지는 값, 재배치 테이블에서 확인- -> 공유(동적)라이브러리는 섹션의 위치를 특정할 수 없어 사용 불가
- R_X86_64_PLT32
- 프로시저 링크 테이블(PLT)를 사용하는 동적 링크
- 함수 호출 시 런타임에 해당 함수의 실제 주소를 해결하기 위해 사용
- 동적 라이브러리에서 많이 사용
- 재배치 테이블(Relocation Table)
정적 링킹
- 정적 라이브러리에 사용
- 프로그램에 필요한 모든 코드가 들어 있음.
- 환경에 크게 관계 없이 실행 가능
- 파일 크기가 매우 큼 ( 용량 낭비 )
- 미리 컴파일된 라이브러리, 재컴파일 필요 X
- 새 버전을 추가하면, 링킹하고 있는 프로그램 다시 컴파일 필요
- 사용하지 않는 함수까지 전부다 포함됨 ( 용량 낭비 )
- 프로그램에 필요한 모든 코드가 들어 있음.
- 링크 타임에 바인딩
- 모든 프로그램이 같은 라이브러리 사용하여도, 각각 동일하게 라이브러리 코드 포함 해야 함
- 외부 링크 방식 심볼 호출 부분은 해당 심볼의 실제 주소 값으로 대체(고정 값)
- 메모리 임의 지점에 불러오면 찾을 수 없음
동적 링킹
- 동적 라이브러리(공유 라이브러리)에 사용
- 실제 물리 메모리에 라이브러리 위치, 가상 테이블로 참조
- 각각의 프로세스에는 고유의 페이지 테이블
- 코드의 크기가 달라, 가상메모리에 위치한 주소가 각자 다름
- ->
가상 메모리
를물리 메모리
변환하는 페이지 테이블이 해결
- 컴파일러를 통해 제작
- 위치와 무관한 코드 (Position Independent Code - PIC) 를 만들라는 의미의
-fpic
인자를 전달해줘야 함.$ g++ -c -fpic foo.cc $ g++ -c -fpic bar.cc $ g++ -shared foo.o bar.o -o libfoobar.so
- 위치와 무관한 코드 (Position Independent Code - PIC) 를 만들라는 의미의
- 실제 물리 메모리에 라이브러리 위치, 가상 테이블로 참조
'공부 > C++' 카테고리의 다른 글
C++ 빌드 과정 (0) | 2025.03.02 |
---|---|
디버그 출력 (0) | 2025.03.02 |
C++ 컨테이너 클래스 (0) | 2025.03.01 |
new&delete (0) | 2025.03.01 |
포인터 (0) | 2025.02.22 |