Linking Error에 대해서

개발 2009. 11. 24. 16:11
프로그래밍 이론의 가장 외곽이라고 해야할까 - 프로그래머가 당장은 몰라도 처음 배울 땐 크게 개의치 않아도 되는

개념 중 하나가 링킹 과정이다. 컴파일 과정은 사실 건너뛰기도 쉬운 것이 우리나라의 현실 같은데 기본기 장만에

그다지 도움이 되는 현실은 아니라고 하겠다.



어쨌든 그 때문인지 초보 프로그래머나 갓 입문한 사람들은 이 링킹 에러가 등장하면 강도 높은 당황에 직면한다.

많이 쓰이는 Visual Studio를 예로 들어보자(gcc에 대해 다루지 않는다고 너무 미워하지 말라).

(6.0 키 셋팅이라는 가정 하에) F4 단축키를 누르거나 에러 목록을 더블 클릭하면 대개 에러가 난 코드로 이동해준다.

아 근데 이놈의 링킹 에러는 에러라고 뜨면서 컴파일이 안되긴 하는데 어디서 에러가 난건지 도통 알려주질 않으니

고치긴 해야겠고 영어라 무슨 소린진 모르겠고(요즘엔 한글 번역이 되어 나오는 것 같아 그나마 다행스럽다?)

설혹 메시지를 알아보더라도 그 뒤로 솰라솰라 나오는 영문자들은 분명 익숙한 글자 - 내가 만든 함수명 - 들을 찾을 수는

있겠는데 내가 설정한 것들과는 완전 딴판이라 결국 알아볼 수가 없다.

이것을 어떻게 고쳐야하겠는고... 느느니 한숨이요 버리느니 성질이라.



링킹 에러를 접하면 일단 당황하지 않는 것이 중요하다. 컴파일 과정을 자세히 들여다보면 각 파일에 대한 컴파일을 끝내고

링킹 과정을 거친다는 것 정도는 알아낼 수 있다.


[컴파일 과정은 무사히 끝나고 링킹 과정에서 에러가 난 모습]


위와 같은 현상이 일어나는 이유는 간단하다. 컴파일러는 초반에 Func 함수의 원형을 보고
 
"아, 어딘가에 이 함수의 본체가 있겠구나" 라고 생각하고 컴파일을 오류 없이 처리 완료했는데,
 
링킹 과정에 들어와서 실제로 엮어보려고 하니 본체가 어디에도 없는
것이다. 그래서 링킹 에러를 뱉게 된다.

왜 이 에러가 컴파일 시기에 에러를 만들지 않고 링킹 때 만들어내는가 하면, Func라는 함수의 본체가 반드시 같은 파일 내에

소속된다는 보장이 없기 때문이다. 원형은 Test.cpp에 되어 있지만 그 함수의 본체는 Func.cpp에 있을지도 모르는 일이다.

때문에 링킹 과정은 여기저기 흩어져 있을 함수들을 찾아 연결시켜주게 되는데 그 과정에서 컴파일 내용과는 달리

찾을 수 없어서 링킹 에러가 난 것이다.


링킹 에러의 원인은 여러 가지가 존재하지만 근본은 이와 다르지 않다. 다만 저 치명적인 에러(fatal error)를 무서워하지 않고

대처하면 된다. void __cdecl Func(... 어쩌구 라고 나오는 건 그나마 가벼운 경우이며 좀 더 왕창 복잡하게 나오는 경우도

있으나 당황하지 말고 "아 내가 뭔가 함수 본체를 안 만들어주었구나" 라고 생각하고 차분히 찾아보자.



다음은 링킹 에러가 많이 나는 예시다. 초보 시절엔 제법 참고가 될 듯 싶다.

1. 함수 원형과 함수 본체의 형식이 다를 때(또는 본체가 없을 떄) - 즉 리턴 형식이나 인자 형식이 다를 때 툭툭 뱉어낸다. 본질적으로 모든 링킹 에러의 원인이다.

2. 어떤 함수를 실제로 호출하는 코드가 하나도 없다면, 원형만 있고 본체가 없다고 해서 링킹 에러가 나지는 않는다.

3. 다형성Overloading을 이용해서 함수를 여러 개 같은 이름으로 작성했을 때, 실제 호출한 형식에 일치하는 놈이 없을 때 - JAVA/C++ 같은 OOP 언어나 다형성 지원 언어에서 대개 일어나지만 본질은 1번과 같다. 잘 찾아서 수정해주도록 하자

4. 함수가 static으로 외부에 공개되지 않았는데 외부에서 호출해대려 할 때
함수의 본체나 원형에 static이 붙으면 그 함수는 해당 파일 내에서만 사용이 가능하다. 다른 파일에서 호출하려 해도 함수 자체가 외부로 유출이 안되기 때문에 없는 것으로 판단하고 에러를 뱉어낸다. 단 이 경우는 대개 컴파일 단계에서 에러가 잡히며,
드문 경우로 어떤 파일에서 void Func(); 라는 원형과는 달리 그 본체가 static void Func() {} 따위의 내용을 갖고 있다면
링킹 에러를 뱉는다. 이 역시 1번과 본질은 같다.

5. 사실 링킹 에러는 비단 함수에 국한되는 것은 아닌데, 변수의 경우 extern int k; 라는 것을 A.cpp에서 선언했는데 어디에도 int k; 라는 전역 변수가 없거나 static int k; 따위로 선언되어 있다면 마찬가지로 찾을 수 없다고 링킹 에러를 뱉게 된다.


기타 등등의 많은 경우가 생길 수 있는데, 결국 링킹 에러는 컴파일러가 찾으려는 놈을 못 찾아서 생기는 문제다.

너무 두려워만 말고 내가 직접 찾아주자!
Posted by OOJJRS
,