이 질문은 번거 롭습니다. 짧은 버전을 시도해 보겠습니다. 일반적으로 실패 할 때 unresolved symbol reference
매우 간단 합니다. 여기서 링커가 찾을 수없는 것을 호출합니다. 링커에 라이브러리를 제공하기 만하면 작동합니다. 때로는 벽에 머리를 두드리는 경우 링커가이 기호를 여기 저기 원하는 이유를 알지 못하는 경우가 있습니다. 적어도 직접적으로는 호출되지 않습니다. 기호가 "여기"에 필요하다고 생각하는 이유를 설명 할 수있는 도구 / 링커 스위치가 있습니까?
원래 질문은 정적 연결에 관한 것입니다. 나는 작은 유틸리티, 몇 줄의 코드, 몇 가지 포함을 가지고 있습니다. 라는 라이브러리와 정적으로 링크 된 유틸리티 lib1
입니다. 의 기호 를 사용하기 때문에 lib1
다른 라이브러리에 대한 종속성이 있다고 가정 해 보겠습니다 . 그러나 아무것도 사용 에서 에서 유틸리티도 아무것도에서 호출 사용 / 그에 의존하지 않을 수 있습니다 . 그러나 앞서 언급 한 작은 유틸리티는 . 첫 번째 질문은 이유입니다. 유틸리티에서는 어디에서나 필요하지 않으며 심지어 그 사용의 기호도lib2
lib1
sym1
lib2
sym1
lib2
lib1
lib2
sym1
sym1
lib1
sym1
유틸리티에서 사용되는 이유는 링커가 처음에이 기호를 찾는 데 귀찮은 이유는 무엇입니까? 두 번째 질문은 포함 체인 sym1
이 내 유틸리티에 기호 를 도입 할 가능성이 있습니다 . 그러면 "이유"에 대한 답변이 나오지만 도입해서는 안됩니다 (적어도 그 이유는 분명하지 않습니다). 두 번째 질문은 어떻게해야 하는가입니다. 링커가 유틸리티가 필요하다고 생각하는 이유 sym1
는 lib2
무엇입니까?
무엇 / 언제 / 이유 : Linux, C / C ++, GCC-9 / Clang-9
글쎄, 분명히 나는 코드와 오류 메시지를 보지 못하는 질문에 대답했습니다. 내 psi- 컨설턴트를 열 시간입니다.
Linux / ELF 대상에서의 링크와 관련하여 링커는 기호를 충족 / 해결하려고 시도하는 동안 섹션 (일명 세그먼트)을 병합 (및 최종 실행 파일로 복사)한다는 사실을 기억하는 것이 중요합니다. 일반적으로 앱에는 .text (코드 세그먼트), .rodata (읽기 전용 데이터) 세그먼트, .data (r / w 초기화 된 데이터) 세그먼트, .bss (초기화되지 않은 데이터) 등이 있습니다. 따라서 필요한 경우 심볼은 세 가지 기능 중 하나입니다. 하나의 컴파일 된 파일에서 파일의 전체 .text 섹션이 선택됩니다. 사용하지 않지만 섹션 함수에있는 경우 다른 것을 호출하면 링커는 응용 프로그램과 관련이 없더라도 만족할 "다른 것"을 검색하기 시작합니다.
또한, C ++에 특정한 것이 있습니다. 가상 함수가있는 클래스의 경우 컴파일러는 각 가상 함수에 대한 포인터를 사용하여 vtable을 생성하고이 테이블을 .rodata 섹션으로 이동합니다. 우리가 코드로 생각하는 것은 실제로 (읽기 전용) DATA 섹션에서 끝납니다.
가상 함수를 하나만 제외하고 모두 정의한 경우 링커는 다음과 같은 오류 메시지를 표시합니다.
/tmp/cc5YTcBb.o:(.rodata._ZTV3CL1[_ZTV3CL1]+0x18): undefined reference to `CL1::fnc2()
문제가 .text가 아닌 .rodata에 있음을 알 수 있습니다.
이야기의 도덕 : 코드와 데이터를 가능한 가장 작은 섹션 / 세그먼트, 연결 원자로 쪼개십시오. 이상적으로, 각 함수는 초기화 된 데이터 또는 R / O 데이터와 함께 자체 섹션으로 이동합니다.
마지막 단계는 -Wl 옵션을 통해 링커에게 사용하지 않는 모든 섹션을 버리도록 (garbage-collect) 지시하는 것입니다.
일반적으로 링커에서 더 많은 RAM을 사용할 것으로 예상해야합니다. 링크 단계는 더 느리지 만 앱은 더 작고 더 빠릅니다.
사용할 명령 줄, GCC 매뉴얼 wrt 옵션 의미를 살펴보십시오.
g++ -fdata-sections -ffunction-sections -fipa-pta main.cpp -Wl,--gc-sections -Wl,-O1 -Wl,--as-needed
이 기사는 인터넷에서 수집됩니다. 재 인쇄 할 때 출처를 알려주십시오.
침해가 발생한 경우 연락 주시기 바랍니다[email protected] 삭제
몇 마디 만하겠습니다