容易检查共享库中的未解决的符号?

我正在编写一个相当大的C ++共享对象库,并遇到一个小问题,使debugging变得很痛苦:

如果我在头文件中定义一个函数/方法,而忘记为它创build一个存根(在开发过程中),因为我正在构build一个共享对象库而不是一个可执行文件,所以编译时不会出现错误,告诉我我有忘记执行该function。 我发现错误的唯一方法是在运行时,最终一个链接到这个库的应用程序会因为'未定义的符号'错误而崩溃。

我正在寻找一种简单的方法来检查编译时是否有所需的所有符号,也许我可以将其添加到我的Makefile中。

我提出的一个解决scheme是通过nm -C -U运行编译的库,以获取所有未定义引用的demangled列表。 问题是这也出现在其他库中的所有引用的列表,如GLibC,当最终应用程序放在一起时,这些链接当然会与这个库链接。 有可能使用nm的输出grep通过我所有的头文件,看看是否有任何相应的名称..但这似乎是疯了。 这当然不是一个不常见的问题,有更好的解决办法吗?

查看链接器选项-z defs / --no-undefined 。 创build共享对象时,如果有未parsing的符号,则会导致链接失败。

如果您使用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); } } 

现在,如果将其构build到共享对象中,它将会成功:

 > 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 

那么testing套件呢? 您创build链接到您需要的符号的模拟可执行文件。 如果链接失败,则意味着您的库接口不完整。

在Linux上(你似乎正在使用) ldd -r a.out应该给你正确的答案,你正在寻找。

更新:一个微不足道的方法来创builda.out来检查:

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

我曾经有同样的问题。 我正在用C ++开发一个组件模型,当然,组件应该在运行时dynamic加载。 想到三个解决scheme,那就是我所申请的:

  1. 花一些时间来定义一个可以静态编译的构build系统。 你会失去一些时间来devise它,但它会节省你很多时间捕捉这些恼人的运行时错误。
  2. 将你的函数分组在熟知和熟悉的部分,这样就可以对函数/存根进行分组,以确保每个相应的函数都有它的存根。 如果花时间logging下来,可以编写一个脚本来检查定义(例如,通过doxygen注释)并检查相应的.cpp文件。
  3. 做几个加载相同库的testing可执行文件,并指定RTL_NOW标志为dlopen(如果你在* NIX下)。 他们将发信号丢失的符号。

希望有所帮助。