VS 2008 컴파일(링킹) - 링크할 라이브러리의 나열순서가 중요!! ??

jeongheumjo의 이미지

윈도우 프로그램 질문입니다. 매번 윈도우 프로그램 질문을 올릴때는 양해를 구합니다.
이곳이 윈도우 프로그램 질문을 올리기에도 가장 좋은 사이트라서요... Devpia 는 답변의 질이 떨어집니다...

제가 신기한 현상을 발견했습니다. 뭐냐면, 비주얼스튜디오에서 동적 링크 라이브러리(암묵적)들을 링크하기 위해서 해당 dll 들의 겁데기 lib 파일들을 적어주죠.

Project Property > Configuration Property > Linker > Input > Additional Dependencies 

에 말입니다. .vcproj 파일에서는
AdditionalDependencies="aaa.lib bbb.lib ccc.lib"

그런데 이렇게 할 때 aaa,bbb,ccc 의 순서가 중요하더라는 것입니다.
즉, 어떤 순서로 써놨든지 컴파일은 모두 잘 됩니다. 그런데 실행시(F5)에 특정 순서로 써놓은 경우만 제대로 실행이 되고 그 순서가 아니면 실행시
Unhandled exception at ..... 

라는 에러창이 뜹니다.

이 디버깅을 하는데에 시간이 꽤 오래 걸렸습니다.
짐작하건대 aaa.lib 가 가지고 있는 심벌을 bbb.lib 를 빌드할 때 사용했던 것이 아닌가 싶습니다. 그런데 그 버전이 조금 달랐던 것입니다. 그렇다면 dll 이 로딩될 때 위 구성 설정에 적어둔 라이브러리 순서로 dll들도 로딩이 되는 것인가, 궁금합니다.

제가 격은 이런 현상이 일반적으로 경험하게 되고 당연한 것이겠죠? 아마 빌드 설정, 특히 라이브러리를 리스트업하는 데에도 순서를 주의해서 리스트업해야 하는 것이겠죠? 이와 관련된 컴파일러의 관련 스펙같은 것이 있을까요? 이와 관련된 어떤 지켜야 하는 규칙이 있을까요? 지금은 그저 막연하게 실행이 잘 되도록 라이브러리들의 순서를 리스트업하고 있거든요....

감사합니다.

winner의 이미지

찾아보니 참조횟수세기군요. http://msdn.microsoft.com/ko-kr/library/zzk20sxw%28v=VS.100%29.aspx
Version이 다르다는 것은 아마도 library가 다르다는 것 같고, symbol이 없으면 통상 Windows에서는 procedure entry point not found(프로시저 시작점을 ... 찾지 못했습니다.) 오류가 나지 않나요?
흠... 제 생각에는 DllMain 구현과 상관있을 것 같은데...
DLL Loading 순서는 재귀적으로 의존관계에 맞춰 loading 될 것 같기에 순서는 별 문제없을 것 같은데요.
실제로 나열한 순서대로 loading 되는지는 모르겠습니다만...

만일 동작이 제대로 되었다고 해도, 우연히 된 것이면 서술된게 없을지도 모릅니다. C++가 뭐, 그렇죠.

익명 사용자의 이미지

그 aaa, bbb, ccc가 윈도우 시스템 dll이면 순서가 아무런 상관이 없는데요.

본문에서 추측한 원인이 맞다면 (aaa심볼을 bbb가 사용한다면) 이건 심볼이 재정의되어서 엉킨 경우니까 순서가 중요하게 되겠죠. 심볼 재정의를 이용해서 긍정적인 효과를 노릴 수도 있지만 (vc 와일드카드 확장하는 목적파일을 이렇게 사용하죠) 본문의 경우는 우발적인 심볼 재정의 같네요.

남이 만든 라이브러리 쓰는 경우라면 어쩔 수 없이 순서를 지켜줘야 하겠지만, 자신이 만든거면 같은 이름의 심볼이 생기지 않게 전처리기 매크로라도 정의해주면 다시 순서는 상관없어질겁니다.

jeongheumjo의 이미지

아 감사합니다.

winner 님은 언제나 친절히 설명해주셔서 늘 감사하고 있습니다.^^;
익명님도 심볼 재정의에 대해 지적해주셔서 감사합니다.

제가 사용하는 문제의 dll 은 OpenCV 라이브러리를 내부적으로 사용할지도 모릅니다. 다른 회사에서 받은 것이라 내부를 알 수가 없습니다. 그런데 그 라이브러리를 사용하는 제 코드에서도 OpenCV 를 사용하고요, 그런데 OpenCV를 사용하는지도 불확실한 상황에서 그 버전역시 제가 사용하는 것과도 다르리라는 추측입니다. 모두 추측일 뿐이라서 답답한 상황이고요,

확실한 것은 위 본문에서처럼 라이브러리를 명시하는 순서가 중요하다는 것입니다.

winner 님이 알려주신 msdn의 설명처럼 명시적 로딩(이라고 하나요?)방식은 아니고 암묵적 링킹과 로딩이 되고 있습니다.

지금 생각해보니 암묵적으로 로딩되도록 하지 말고 명시적으로 지연 로딩을 해보면 차이점을 더 느끼기 쉽지 않을까 생각해봅니다.
명시적으로 로딩 순서를 바꿔보면서 로딩시 문제가 없는지 본다면 도움이 되지 않을까...

그런데 제게 시간이 별로 없고, 단순히 라이브러리를 명시하는 순서를 조정함으로써 문제가 발생하지 않는 다는 것이 문제입니다.
이 문제의 원인을 알아내고 싶은데 시간 제약이 있고 문제가 재현되지 않음으로써(원인은 모르지만) 동기가 작아졌으니까요...

제가 나중에라도 이 문제의 원인을 알게 된다면 이 스레드에 그 내용을 밝혀보겠습니다.

감사합니다.

winner의 이미지

제 기억으로 Visual C++ 에서 Debugger와 함께 실행하면 dll loading 되는게 출력화면에서 보였던 것으로 기억합니다. 그거 봐도 도움은 되겠네요. 문서를 통해서 확실히 정의된 것을 확인하는 것은 아니겠습니다만...

익명 사용자의 이미지

정말 심볼 재정의인지 확인하는 방법은 map파일을 만들어서 어느 import라이브러리에서 심볼이 링크되는지를 확인하면 금방 알 수 있어요. 순서를 바꾸었을때 어떤 심볼이 오는 라이브러리가 달라지면 당첨. 아마도 awk이나 perl등으로 libname:symbol 식으로 되어있는 열만 추출해서 정렬비교해보는게 훨씬 빠르겠죠. (물론 꼭 확인하겠다면 이런 방법도 있다는 얘기지 이렇게 해야만 한다는건 아닙니다.)

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.