开发者社区 问答 正文

使用tcl8.6共享库,遇到错误提示undefined reference to

项目中用到了tcl8.6的共享库,把tcl的源码下载后在ubuntu上将tcl的库编译出来了。但是在编译项目的时候总是报未定义引用的错误,我检查了自己编译出来的libtcl8.6.so,这个共享库中是有tclStringType的定义的,也检查了声明tclStringType的头文件,编译tcl共享库时的头文件与编译项目时的头文件是一致的。
以下是共享库符号检查和编译的结果,跪求武林高手出手相帮,不胜感激!
nm -l /home/water/Documents/eaf/kit/test/lib/Linux_3.19.0_i686/liboms_shr.so|grep tclStringType
U tclStringType
nm -l /usr/lib/i386-linux-gnu/libtcl8.6.so|grep tclStringType
001a1034 d tclStringType
gcc -g -o /home/water/Documents/eaf/kit/test/bin/Linux_3.19.0_i686/TableDump Linux_3.19.0_i686/TableDump.o -L/home/water/Documents/eaf/kit/test/lib/Linux_3.19.0_i686 -loms0_shr -L/home/water/Documents/eaf/kit/test/lib/Linux_3.19.0_i686 -loms_shr -L/home/water/Documents/eaf/kit/test/lib/Linux_3.19.0_i686 -lstub -L/usr/lib/i386-linux-gnu -ltcl8.6 -L/usr/lib/i386-linux-gnu -lpthread -L/usr/lib/i386-linux-gnu -lresolv -L/usr/lib/i386-linux-gnu -lm -L/usr/lib/i386-linux-gnu -lc -Xlinker --rpath-link -Xlinker /home/water/Documents/eaf/kit/test/lib/Linux_3.19.0_i686
/home/water/Documents/eaf/kit/test/lib/Linux_3.19.0_i686/liboms_shr.so: undefined reference to tclEmptyStringRep'
/home/water/Documents/eaf/kit/test/lib/Linux_3.19.0_i686/liboms_shr.so: undefined reference totclStringType'
/home/water/Documents/eaf/kit/test/lib/Linux_3.19.0_i686/liboms_shr.so: undefined reference to `tclFreeObjList'

展开
收起
杨冬芳 2016-07-14 15:14:24 3528 分享 版权
阿里云 AI 助理回答

根据您提供的信息,问题的核心是编译项目时出现了未定义引用的错误,具体涉及 tclStringTypetclEmptyStringReptclFreeObjList 等符号。尽管您确认这些符号在 libtcl8.6.so 中存在,并且头文件一致,但链接阶段仍然报错。以下是可能的原因分析及解决方案:


1. 符号可见性问题

动态库中的符号可能由于编译选项或链接器行为导致不可见。例如,某些符号可能被标记为内部符号(statichidden),从而无法被外部链接。

检查步骤:

  • 使用 nm -D /usr/lib/i386-linux-gnu/libtcl8.6.so | grep tclStringType 检查符号是否为动态导出符号。
    • 如果输出中没有 TD 标志(表示全局符号),说明该符号未被导出。
  • 如果符号未导出,可能是 Tcl 的构建配置限制了符号的可见性。

解决方案:

  • 修改 Tcl 的源码编译配置,确保符号被导出:
    • 在编译 Tcl 时,添加 -fvisibility=hidden 并显式导出需要的符号。
    • 或者重新编译 Tcl,移除符号隐藏选项(如 -fvisibility=hidden)。

2. 链接顺序问题

链接器对库的解析顺序敏感。如果依赖库的顺序不正确,可能导致未定义引用错误。

检查步骤:

  • 您的链接命令中,-ltcl8.6 出现在 -loms_shr 之后。链接器会按照从左到右的顺序解析符号,因此 liboms_shr.so 中的符号可能无法找到 libtcl8.6.so 中的定义。

解决方案:

  • 调整链接顺序,将 -ltcl8.6 放在所有依赖它的库之前:
    gcc -g -o /home/water/Documents/eaf/kit/test/bin/Linux_3.19.0_i686/TableDump \
      Linux_3.19.0_i686/TableDump.o \
      -L/usr/lib/i386-linux-gnu -ltcl8.6 \
      -L/home/water/Documents/eaf/kit/test/lib/Linux_3.19.0_i686 -loms_shr \
      -L/home/water/Documents/eaf/kit/test/lib/Linux_3.19.0_i686 -lstub \
      -lpthread -lresolv -lm -lc \
      -Xlinker --rpath-link -Xlinker /home/water/Documents/eaf/kit/test/lib/Linux_3.19.0_i686
    

3. 动态库路径问题

即使符号存在于 libtcl8.6.so 中,链接器可能未能正确找到该库。

检查步骤:

  • 确保 /usr/lib/i386-linux-gnu/libtcl8.6.so 是正确的路径,并且该库文件完整无误。
  • 使用 ldd /home/water/Documents/eaf/kit/test/lib/Linux_3.19.0_i686/liboms_shr.so 检查 liboms_shr.so 是否正确链接到 libtcl8.6.so

解决方案:

  • 如果 ldd 输出显示未找到 libtcl8.6.so,可以通过以下方式修复:
    • 设置环境变量 LD_LIBRARY_PATH,包含 /usr/lib/i386-linux-gnu
    export LD_LIBRARY_PATH=/usr/lib/i386-linux-gnu:$LD_LIBRARY_PATH
    
    • 或者在链接时显式指定运行时库路径:
    gcc ... -Wl,-rpath,/usr/lib/i386-linux-gnu
    

4. 版本兼容性问题

您提到使用的是 tcl8.6,但可能存在多个版本的 Tcl 库共存,导致链接器选择了错误的版本。

检查步骤:

  • 使用 readelf -d /home/water/Documents/eaf/kit/test/lib/Linux_3.19.0_i686/liboms_shr.so | grep NEEDED 检查 liboms_shr.so 依赖的库。
  • 确认依赖的 libtcl8.6.so 版本与实际使用的版本一致。

解决方案:

  • 删除系统中其他版本的 Tcl 库,确保只保留 tcl8.6
  • 或者在编译和运行时显式指定库路径,避免版本冲突。

5. 静态库与动态库混合问题

如果项目中同时使用了静态库和动态库,可能会导致符号冲突或未定义引用。

检查步骤:

  • 确认 liboms_shr.solibtcl8.6.so 都是动态库。
  • 如果 liboms_shr.so 是静态库,则需要确保其依赖的符号在链接时已完全解析。

解决方案:

  • 如果 liboms_shr.so 是静态库,尝试将其改为动态库,或者在链接时显式包含所有依赖的静态库。

6. 其他可能原因

  • 头文件与库不匹配:虽然您确认头文件一致,但仍需检查是否有多个版本的头文件存在。
  • 编译器优化问题:某些编译器优化可能导致符号被丢弃。尝试关闭优化选项(如 -O0)重新编译。

总结建议

根据上述分析,建议按以下步骤排查和解决问题: 1. 确认 libtcl8.6.so 中的符号是否为动态导出符号。 2. 调整链接顺序,确保 -ltcl8.6 在所有依赖它的库之前。 3. 检查动态库路径,确保链接器能够正确找到 libtcl8.6.so。 4. 排查版本兼容性问题,避免多个版本的 Tcl 库共存。 5. 确认 liboms_shr.solibtcl8.6.so 的类型一致(均为动态库或静态库)。

如果问题仍未解决,请提供更详细的编译日志和环境信息,以便进一步分析。

有帮助
无帮助
AI 助理回答生成答案可能存在不准确,仅供参考
0 条回答
写回答
取消 提交回答
问答分类:
问答地址: