본문 바로가기
컴퓨터/디버깅

unresolved external symbol

by adnoctum 2010. 4. 19.



   아마도 가장 자주 보이는 에러 중의 하나가 아닐까 한데, unresolved external symbol 이란, 말 그대로 그 의미를 알 수 없는(이해할 수 없는, 해결할 수 없는) symbol 이 발견되었다는 의미이다. 컴파일러에게 'unresolved' 란,  변수의 경우 아직 선언되지 않은 변수거나, 다른 곳에 선언되어 있는 변수라고 extern 키워드로 지정했지만 결국은 찾을 수 없었던 변수였을 경우, 또한 함수의 경우, 함수를 호출하는 곳이 있었기 때문에 일단 함수의 헤더를 이용해서 함수를 호출하는 부분은 메꾸어 놓았는데 막상 그 함수를 구현해 놓은 부분은 찾지 못한 경우를 의미한다.

환경: Visual C++ 9.0 (VS2008) on Windows XP SP2

IICGComponent.obj : error LNK2001: unresolved external symbol "public: char __thiscall CCrestAreaExtractor::get_termination_code(void)const " (?get_termination_code@CCrestAreaExtractor@@QBEDXZ)


위와 같은 경우는 get_termination_code(void) const 라는 형태의 함수를 호출을 했지만 아직 구현이 되어 있지 않아서 찾을 수 없기 때문에 발생한 것이다.

C++의 경우, 함수의 헤더 (주로 .h 파일에 있는 것)과 함수의 정의 (주로 .cpp 파일에 있는 것) 가 따로 작성될 경우가 많다. exe 를 만드는 과정은 크게 1. compile 2. link 의 두 과정으로 볼 수 있는데, 컴파일은 .cpp 파일에 구현되어 있는 것을 기계어로 변환하는 과정이다. 이 때, 만약 다른 함수를 호출하는 부분이 있으면, 함수 호출 규칙(prototype)이 제대로 맞는지를 확인하기 위하여 h 파일에 있는 함수의 구조 정보(prototype)이 필요하다. 반면 실제로 그 함수가 구현된 기계어 코드는 필요하지 않고, 단지 프로그램의 제어권을 그 함수가 구현된 곳으로 넘길 뿐이다. 그렇기 때문에 함수 역시 포인터와 같은 것이다. 그렇게 일단 컴파일을 한 후, 이제 함수가 호출되는 부분들을 임시로 연결시켜 놓았던, 호출되는 함수의 실제 구현 부분을 찾아서 임시로 연결시켜 놓았던 주소에 실제 함수의 시작 부분을 넣으려는 작업을 시도한다(link). 그런데 만약 호출된 함수의 실제 구현부분을 찾지 못할 경우 제대로 link를 할 수 없고, 바로 이 때 unresolved external symbol 이란 에러가 발생할 수 있다. 이 과정을 그림으로 보면 다음과 같다.




함수가 위처럼 기계어로 코드가 변환되면서 넘어 가다가, test() 라는 외부 함수를 만나면 일단 그 위치를 임시 함수 포인터로 대체를 해 놓고 계속 처리한다. 만약 이 과정이 끝나면, 다음과 같이 완전히 link 를 하기 시작한다.





test() 라는 함수의 실제 구현부분의 주소로 프로그램의 제어권을 넘겨 준다. 그리고 test() 가 끝나면 다시 원위치로 돌아 와 계속 작업을 진행하게 된다. 위와 같은 상황에서 test() 가 구현되어 있는 부분이 없다면 test() 가 호출되는 순간 프로그램의 제어권을 넘길 곳을 찾지 못할 것이다. linker 는 일단 기계어로 모두 번역을 하고, 함수 호출부분은 함수의 주소값으로 임시로 대체를 해 놓고, 후에 실제로 그 함수가 구현된 주소값으로 임시로 써 놓았던 함수 주소를 제대로 적어 놓음으로 link를 완성시킨다. 이 과정에서 link 시킬 함수구현부분을 찾지 못하면 바로 unresolved external symbol 이란 에러가 발생할 수 있는 것이다.


외부 라이브러리를 사용할 경우, 컴파일이야 헤더파일이 있으면 되겠지만 실제 함수가 구현되어 있는 라이브러리 파일 (.lib 나 .dll, 또는 .a 나 .so) 이 없으면 링크 과정에서 위와 같은 에러가 날 수 있으므로 별도의 라이브러리를 사용할 경우 컴파일러에게 외부라이브러리 사용을 명시해야 할 경우가 많다. gcc의 경우

g++ test.cpp -o test -lgmp -lgmpxx

처럼 -l option 뒤에 외부라이브러리를 설정해 줄 수 있다. 각 라이브러리의 사용 설명서에 어떻게 링크시키는지 대부분 잘 나와 있으므로 그것을 따른다. VC++의 경우 Project Settings이나 Property Pages에서 적당한 곳에 써 넣으면 된다.

외부 라이브러리 설정 (VC++6.0)


VC++ 6.0 의 경우 Project Settings 메뉴에서 Link 탭의 Ojbect/library modules 항목에, 사용할 외부 라이브러리를 지정할 수 있다.




외부 라이브러리 설정 (VC++9.0)


VC++9.0 의 경우 Property Manager에서 Property Pages로 들어가서, Linker 항목의 Input 항목에서 Additional Dependencies 항목에, 외부라이브러리를 명시해서 사용할 수 있다.