공유 라이브러리에서 해결되지 않은 기호를 쉽게 확인 하시겠습니까? 빌드하고 있기 때문에 컴파일 타임에 오류가 발생하지

상당히 큰 C ++ 공유 객체 라이브러리를 작성 중이며 디버깅을 어렵게 만드는 작은 문제가 발생했습니다.

헤더 파일에 함수 / 메서드를 정의하고이를위한 스텁을 만드는 것을 잊은 경우 (개발 중), 실행 파일이 아닌 공유 객체 라이브러리로 빌드하고 있기 때문에 컴파일 타임에 오류가 발생하지 않는다는 오류가 나타나지 않습니다. 그 기능을 구현하는 것을 잊었습니다. 내가 뭔가 잘못되었음을 알아내는 유일한 방법은 런타임에이 라이브러리에 연결하는 응용 프로그램이 결국 ‘정의되지 않은 기호’오류로 넘어갈 때입니다.

컴파일 타임에 필요한 모든 기호가 있는지 확인하는 쉬운 방법을 찾고 있습니다. 아마도 Makefile에 추가 할 수있는 것입니다.

내가 생각 해낸 한 가지 해결책은 컴파일 된 라이브러리를 실행하여 nm -C -U정의되지 않은 모든 참조 목록을 가져 오는 것입니다. 문제는 GLibC와 같은 다른 라이브러리에있는 모든 참조 목록과 함께 나타납니다. 물론 최종 응용 프로그램이 함께 작성 될 때이 라이브러리와 함께 연결됩니다. 내 모든 헤더 파일 nmgrep통해 to 의 출력을 사용하고 해당하는 이름이 있는지 확인할 수 있습니다. 확실히 이것은 드문 문제가 아니며 더 나은 해결 방법이 있습니까?



답변

링커 옵션 -z defs/을 확인하십시오 --no-undefined. 공유 객체를 만들 때 해결되지 않은 심볼이 있으면 링크가 실패합니다.

gcc를 사용하여 링커를 호출하는 경우 컴파일러 -Wl옵션을 사용 하여 옵션을 링커에 전달합니다.

gcc -shared ... -Wl,-z,defs

예를 들어 다음 파일을 고려하십시오.

#include <stdio.h>

void forgot_to_define(FILE *fp);

void doit(const char *filename)
{
    FILE *fp = fopen(filename, "r");
    if (fp != NULL)
    {
        forgot_to_define(fp);
        fclose(fp);
    }
}

이제 공유 객체로 빌드하면 성공합니다.

> gcc -shared -fPIC -o libsilly.so silly.c && echo succeeded || echo failed
succeeded

그러나을 추가 -z defs하면 링크가 실패하고 누락 된 기호에 대해 알려줍니다.

> gcc -shared -fPIC -o libsilly.so silly.c -Wl,-z,defs && echo succeeded || echo failed
/tmp/cccIwwbn.o: In function `doit':
silly.c:(.text+0x2c): undefined reference to `forgot_to_define'
collect2: ld returned 1 exit status
failed

답변

Linux (사용중인 것으로 보이는) ldd -r a.out에서는 원하는 답을 정확하게 제공해야합니다.

업데이트 : 확인할 사소한 방법 a.out:

 echo "int main() { return 0; }" | g++ -xc++ - ./libMySharedLib.so
 ldd -r ./a.out

답변

testsuite는 어떻습니까? 필요한 기호에 연결되는 모의 실행 파일을 만듭니다. 연결이 실패하면 라이브러리 인터페이스가 불완전 함을 의미합니다.


답변

나는 한 번 같은 문제가 있었다. 저는 C ++로 구성 요소 모델을 개발하고 있었으며, 물론 구성 요소는 런타임에 동적으로로드되어야합니다. 세 가지 해결책이 떠오르는데 그게 제가 적용한 것입니다.

  1. 정적으로 컴파일 할 수있는 빌드 시스템을 정의하는 데 시간이 걸립니다. 엔지니어링에 약간의 시간을 잃게 될 것이지만 이러한 성가신 런타임 오류를 포착하는 데 많은 시간을 절약 할 수 있습니다.
  2. 잘 알려져 있고 잘 이해 된 섹션으로 함수를 그룹화하여 함수 / 스텁을 그룹화하여 각 해당 함수에 해당 스텁이 있는지 확인할 수 있습니다. 문서화하는 데 시간을 할애하면 정의를 확인하는 스크립트 (예 : doxygen 주석을 통해)를 작성하고 해당 .cpp 파일을 확인할 수 있습니다.
  3. 동일한 라이브러리 세트를로드하고 RTLD_NOW 플래그를 dlopen에 지정하는 여러 테스트 실행 파일을 수행하십시오 (* NIX에있는 경우). 그들은 누락 된 기호를 알릴 것입니다.

도움이되기를 바랍니다.