Linking 101

아래 글은 외국 블로그의 글을 무단(!)으로 번역하여 포스팅한것 입니다.

주소 : http://vladimir_prus.blogspot.com/2009/06/linking-101.html

최근에, 나는 점점 더 많은 사람들이 링킹 과정에서 문제를 겪는 것을 보게된다.

마치 가장 재수없는 경우의 에러이거나 보통 사람은 고칠수 없는 것처럼 여긴다.

그럴만한데는 여러가지 이유가 있는데,

대학교에서 자바를 기본 언어로 사용하고 있다는 것과 and alarming spread of header-only-philia. (?)

이제 나는 링크시 발생하는 에러를 진단할 수 있는 간단한 검사방법을 알려주겠다.

우선 몇가지 기본지식을 살펴보자.

만약 당신의 일이 C++로 프로그래밍 하는 것이라면, -l 옵션과 -L 옵션이 무엇인지, 어떻게 다른것인지 알 필요가 있다.

또한 full path가 주어진 라이브러리 파일( .a 또는 .so 또는 .lib)은, 2가지 방식으로 링크를 할 수 있다.

만약 당신이 위와 같은 내용에 대해서 모른다면, 희망이 없다. 그냥 다른 일자리를 알아보는게 좋은것같다.

위 내용에 대해 알고 있다면, 가장 흔한 에러인 ‘undefined symbol’ 에서를 분석하는 것을 살펴보자.

첫번째로, 못찾은 심볼이 어디에 정의되어 있는지 살펴본다.

경험에서 우러나온 추측이 대체로 도움이 된다.

예를들어, boost::system::foobar라는 심볼 이름은 대부분 Boost.System 라이브러리에 담겨져 있다.

( 많은 사람들이 그런 추측을 하지 못한다는것이 놀랍다 )

그리고나서, 컴포넌트의 문서를 살펴보거나, 리눅스 패키지를 살펴봄으로써 logical 컴포넌트들을 링크시키게 할 수 있을지 찾아보자.

예를 들어, -lboost_filesystem 같은 링커 커멘드를 추가해야 한다는 것을 결정해야 한다.

두번째로, 사용된 physical 라이브러리 파일이 맞는것인지 확실하게 확인한다.

그리고 링커가 당신이 바라지 않은 다른 버전의 라이브러리 파일을 디렉토리에서 참조하고 있는건 아닌지도 확인해보자.

만약 당신이 프로그램을 링킹하는 동안에 에러가 발생하면다면 GNU 링커에 -t 옵션을 줄 수 있다.

(또는 -Wl,-t 를 gcc command link에서 사용할 수 있다)

해당 옵션은 -lfoo 명령과 같이 사용자가 명시한 라이브러리를 포함한 링킹에 사용되는 모든 라이브러리 파일의 전체 경로를 출력해 준다.

정적 링킹을 할때에는, 정적 라이브러리 안에 어떤 오브젝트 파일들이 사용되었는지 알려준다.

만약 당신이 프로그램을 수행중에 에러를 만나게 된다면, 당신은 LD_DEBUG 환경 변수를 이용할 수 있다.

만약 당신이 프로그램을 돌리기 전에 이 변수를 설정해 놓았다면, 당신은 유용한 값의 목록을 얻을 수 있을 것이다.

우리의 경우 가장 중요한 변수를 파일들이다.

세번째로, 만약 당신이 제대로된 라이브러리를 링크한건처럼 보인다면, 3가지 가능성이 있다.

첫번째,, 아마도 라이브러리가 우리가 원하는 심볼을 가지고 있지 않다.

이것은 당신의 컴파일 하는 동안 잘못된 해더를 사용하면 발생할 수 있다.

그리고 이것은 gcc에게 -save-temps라는 옵션을 줌으로써 디버깅할 수 있다. 이 옵션은 .ii 파일을 생성하고 그것을 확인하자.

두번째,, 심볼은 확실히 라이브러리안에 있는 거처럼 보이지만, 다른 calling convention(윈도우에서)를 사용하거나,

wchat_t 모드이거나(또한 윈도우에서) 또는 다른 종류의 파라미터를 사용하거나, 또는 다른 namespace를 사용하는 경우이다.

이 경우, 당신은 라이브러리의 요구사항에 맞도록 어플리케이션의 컴파일 옵션을 바꾸어 줌으로서 해결 할 수 있다.

마지막으로, 라이브러리에 버그가 있어서 심볼이 잘못된 경우이다. 이경우 해당 개발자에게 연락을 하자.

위의 3가지 경우들을 구분짓기 위해서는, 당신은 라이브러리의 심볼 목록을 일일이 검사해야 할 필요가 있다.

gcc를 쓴다면 ‘nm’커멘드가 정적 라이브러리를 살펴보는데 도움이 되고, 공유 라이브러리를 분석하는데는 ‘readelf’가 도움이 된다. (Unix 전용)

아직 윈도우에서는 멋진 방법을 찾지 못했다. 제안은 언제나 환영

이것들은 일반적인 경우이다. 아래에는 특정 경우에 일반적인 문제점들을 나열했다.

이 리스트는 완벽하지 않다. 따라서 당신이 다른 종료의 사례를 알고 있으면 알려줘라.

Static linking.

정정 링크의 경우에는,커멘드 라인의 라이브러리 순서가 문제를 발생한다.

따라서 만약 당신 오브젝트 파일의 심볼을 링킹하려고 하지 않는다면,

당신은 라이브러리의 순서를 재정의하거나 —start-group 옵션을 사용해야 할지도 모른다.

ld documentation을 보면 더 자세한 내용이 나와있다. 최근에는 —start-group 옵션의 성능 비용은 문제가 되지 않는다.

References to vtable.

GNU C++ 컴파일러는 때때로 unresolved reference to ‘vtable for SomeClass’ 문제를 출력한다.

이것은 SomeClass의 메소드가 정의되어 있지 않다는 이야기이다. GCC FAQ를 살펴봐라.

Windows DLLs.

윈도우즈에서, 만약 어플리케이션이 DLL안에 있는 함수를 사용하기를 원한다면,

DLL과 application둘다 declspec(dllexport) 와 declspec(dllimport)를 사용해야 한다.

만약 하지 않는다면, 링커를 에러는 발생한다.

mingw 에서, 일반적인 에러는 undefined reference to `imp__WHATEVER’ 이다.

이것은 라이브러리는 정적인데, 어플리케이션이 원하는 것은 공유 라이브러리 하는 것이다.

Windows import libraries.

윈도우에서 DLL파일을 직접적으로 link하는 것은 불가능하다.

대신에, 중요한 라이브러리는 일반적으로 링커에게 /IMPLIB 옵션을 전달해 줌으로써 만들고 사용할 수 있다.

만약 링커가 아무런 에러를 발생하지 않았음에도, 라이브러리를 참조하지 않고 있다면,

그것은 DLL파일 안에 exported된 어떠한 함수도 없다는 확실한 신호이다.

코드를 다시 한번 확인해보고 __declspec(dllexport)를 추가해 준다.

64-bit compilation.

64비트 어플리케이션을 빌드 할 때, “relocation RX8664_32″에 대해 말하고 있는 어떤 에러를 만날수 있다.

이건 -fPIC 옵션에 대한것임을 암시한다.

64비트 어플레이케션은 오직 -fPIC 옵션으로 컴파일된 코드만을 참조할 수 있는 이슈가 있다.

만약 어떤 정적 라이브러리를 링크하는 것은 대비하여(?–__?), 이들 라이브러리들은 -fPIC 옵션으로 컴파일 되어야 한다.

Advertisements

답글 남기기

아래 항목을 채우거나 오른쪽 아이콘 중 하나를 클릭하여 로그 인 하세요:

WordPress.com 로고

WordPress.com의 계정을 사용하여 댓글을 남깁니다. 로그아웃 /  변경 )

Google+ photo

Google+의 계정을 사용하여 댓글을 남깁니다. 로그아웃 /  변경 )

Twitter 사진

Twitter의 계정을 사용하여 댓글을 남깁니다. 로그아웃 /  변경 )

Facebook 사진

Facebook의 계정을 사용하여 댓글을 남깁니다. 로그아웃 /  변경 )

w

%s에 연결하는 중