참고 문헌 : 씹어먹는 C++ - <20 - 3. 코드 부터 실행 파일 까지 - 링킹 (Linking)>

저장 방식 지정자 (Storage class specifier)

  • static
  • thread_local
  • extern
  • mutable <- 저장 기간과 링크 방식에 영향x
  • auto <- c++11 부터 제거됨 (auto 키워드로 대체)
  • register <- c++17 부터 제거됨

저장 기간 (Storage duration)

  • ___ 객체들에게만 해당
  • 자동 저장 기간
    • scope{} 안에 정의 된 녀석들
      • static, extern, thread_local 키워드 지정 제외
    • 지역 변수
  • static 저장 기간
    • 프로그램 시작할 떄 할당, 끝날 때 소멸
    • 함수 밖에 정의된 것들 (전역변수,namespace 단위)
    • static or extern 정의 객체
  • 쓰레드 저장 기간
    • 쓰레드 시작할 떄 할당, 종료될 떄 소멸
    • 각 쓰레드들이 해당 객체 복사본 가짐
    • thread_local 선언 객체
  • 동적 저장 기간
    • 동적 할당 함수를 통해 할당, 해제되는 객체 (new, delete)
    • 링커에서 어디에 배치 할 지 중요 정보로 사용됨

링크 방식(lINKAGE)

  • 링크 방식 없음 (No linkage)
    • 지역 함수들은 {}안에 링크 방식이 없는 상태로 정의되어 있음
  • 내부 링크 방식 (Internal Linkage)
    • static으로 정의된 함수, 변수, 템플릿 함수, 템플릿 변수 등.
    • 같은 TU 안에서만 참조
      • C#의 static이 다른 파일에서 사용가능한 것과 달리, Cpp에서는 사용 불가.
  • 외부 링크 방식 (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)를 사용하는 동적 링크
        • 함수 호출 시 런타임에 해당 함수의 실제 주소를 해결하기 위해 사용
        • 동적 라이브러리에서 많이 사용

정적 링킹

  • 정적 라이브러리에 사용
    • 프로그램에 필요한 모든 코드가 들어 있음.
      • 환경에 크게 관계 없이 실행 가능
      • 파일 크기가 매우 큼 ( 용량 낭비 )
    • 미리 컴파일된 라이브러리, 재컴파일 필요 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

'공부 > 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

+ Recent posts

let textNodes = document.querySelectorAll("div.tt_article_useless_p_margin.contents_style > *:not(figure):not(pre)"); textNodes.forEach(function(a) { a.innerHTML = a.innerHTML.replace(/`(.*?)`/g, '$1'); });