rein's world

Library 구성 삽질

지난 주말에 출근해서 하루간 삽질한걸 가지고 오늘 연동 테스트를 하는데, Azyu 컴퓨터에서 네트웍에서 온 패킷을 처리못하는 상황이 발생.

  1. 네트웍으로 온 데이터를
  2. 길이와 아이디를 이용해서
  3. 의미단위로 쪼갠 후
  4. 몇 가지 기본 타입의 조합으로 바꾼 후, 윗단으로 전달

하는 일련의 과정을 거친다.

근데 3 단계에서 raw binary stream을 C++이 인식하는 각종 타입으로 바꾸는 과정에서 에러가 났다. 정확히는 특정 구조체를 뽑아내는 부분으로 넘어가질 않는다. 심지어, 디버그 모드에서 break-point 조차 설정할 수 없는 이상한 상태 Orz

UnitTest를 확인해보면, 절대로 그런 일은 일어나지 않는다. 덤으로 조금 더 살펴 본 결과 한가지 타입에서만 계속 발생하는걸 확인.  그래서 아예 해당 부분을 읽어들이는 코드를 통째로 바꿔버렸다. (원래는 해당 구조체의 특정 함수를 호출함) 그랬더니 제대로 동작?!

내가 딴거 처리하는 사이에 동료들이 원인을 찾았는데, map 파일을 뜯어본 결과, 해당 함수가 들어있어야 할 파일이 아니라 딴 obj 파일에 링크되었고, 링크된 오브젝트 파일의 내용은 필요로 하는 함수와 동작이 다르다는 것.

원인은, 좀 이력이 긴 내용인데, 부모가 버리고 간 코드(…이하 S)를 수정하다보니 생긴 일.

  1. 약 1년 2개 월전에 팀에서 작성한 라이브러리(다이어그램의 ArchivedLibrary.lib)을 S에 추가
  2. 약 3개월 전부터, 기반 라이브러리 코드를 팀에서 작성한 라이브러리로 변경 작업 시작
  3. 차근차근 라이브러리가 추가되고 / 테스트가 진행

인데, 오늘 확인한 바로는 좀 단순화 해서 말하면 아래와 같은 상황이 된 것. 네모는 라이브러리들, 타원은 응용 프로그램 바이너리, 혹은 묶인(archived) 라이브러리 바이너리. 화살표는 의존성을 의미한다. 문제를 일으킨 녀석이 회색 타원에 들어가있는 archivedlibrary.lib.

CatastrophicLibraryHierarchy

처음에 static link 형태로 추가했던 (일부 헤더와 lib 파일 하나) ArchivedLibrary.lib 을 사용해서 응용 프로그램을 작성했다. 그런데 이 프로그램의 기반 코드 일부를 새 라이브러리로 작성했고, 여기서는 .lib을 static-link한게 아니라 VisualStudio의 project-dependency를 거는 방식으로 링크가 이루어지게 했다(사실 이것도 내부적으론 static-link의 형태지만). 근데 그 동안 잘 돌다가, 오늘에 와서 뻥 터진 것 –_-;

그래서 아예 뜯어 헤치고는 .lib 들이 다 드러나게 바꿔야 했다. (정확히는 utility.lib에 해당하는 녀석만 링크되게하고, 이 녀석이 쓰는 Common.lib은 그냥 링크가 되도록 설정)

여기서 의문: 왜 archivedlibrary.lib과 common.lib에 같은 심볼이 있는데 linker 에러가 나지 않고, 이상한 바이너리를 만들어서 나를 괴롭혔을까? –_-; 누가 답 좀 Orz

결론: 원인은 모르겠지만 — 정확히 말하자면, 저런 이상한 링크가 이뤄지는 기저 메커니즘을 모르겠다 — 이 현상에 대한 대처는 간단하다.

  • 맨 밑단에서 쓰는 코드(라이브러리)들이 겹칠 수 있는 경우, 합쳐진 archive를 내놓는게 아니라 개별 라이브러리를 토해내게 한다
  • 복잡해서 다루기 힘든 경우, 최종적으로 다 모아놓은 상태에서 묶는다(VisualStudio의 lib.exe나 *nix의 ar를 사용)