Computer >> 컴퓨터 >  >> 프로그래밍 >> C++

GCC에서 라이브러리 링크 순서가 때때로 오류를 일으키는 이유

GCC 링크 오류, 왜 라이브러리 순서가 문제가 될까?

이러한 종류의 오류는 기본적으로 컴파일 과정의 링커(linker)에서 비롯됩니다. 링커의 기본 동작 방식은 현재 프로그램이 필요로 하는 시점에 아카이브 라이브러리(정적 라이브러리)에서 해당 코드를 가져오는 것입니다.

링커의 기본 동작 원리

링커는 명령줄에 나열된 파일을 왼쪽에서 오른쪽으로 처리하면서, 그 시점까지 아직 해결되지 않은(undefined) 심볼만 라이브러리에서 찾아 연결합니다. 따라서 어떤 라이브러리가 다른 라이브러리에 정의된 함수를 참조한다면, 참조하는 쪽(호출자)이 반드시 참조되는 쪽(피호출자)보다 먼저 나와야 합니다. 이를 흔히 “호출자가 피호출자보다 앞선다(caller before callees)”는 규칙이라고 표현합니다.

해결 방법 두 가지

이 문제는 크게 두 가지 방법으로 해결할 수 있습니다.

1. 링커 옵션으로 기본 동작 변경하기
플래그를 사용해 링커의 기본 동작을 바꾸면 순서에 얽매이지 않고 링크할 수 있습니다. 예를 들어 GNU ld의 경우 --start-group--end-group 옵션으로 라이브러리들을 묶으면, 링커가 그룹 내 라이브러리를 반복해서 검사하며 미해결 심볼을 모두 찾아냅니다. 다만 이 방식은 링커가 여러 번 탐색을 수행하기 때문에 링크 시간이 길어질 수 있다는 단점이 있습니다.

2. 라이브러리 순서를 올바르게 정렬하기
명령줄에서 라이브러리들을 올바른 순서로 배치하는 방법입니다. 의존 관계가 복잡한 대규모 프로젝트에서는 사람이 일일이 순서를 정하기 어려운데, 이때 tsort(위상 정렬 도구)나 로더(loader)의 도움을 받아 라이브러리 간 의존 관계를 분석하고 순서를 재배열·수정할 수 있습니다.

정리

결국 GCC의 링크 오류는 링커가 심볼을 한 방향으로만 탐색하는 특성에서 비롯됩니다. 빌드 속도가 중요하다면 라이브러리 순서를 직접 정렬하는 것이 좋고, 편의성이 우선이라면 링커 옵션을 활용하는 것이 효율적입니다.