项目中用到了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'
版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。
根据您提供的信息,问题的核心是编译项目时出现了未定义引用的错误,具体涉及 tclStringType
、tclEmptyStringRep
和 tclFreeObjList
等符号。尽管您确认这些符号在 libtcl8.6.so
中存在,并且头文件一致,但链接阶段仍然报错。以下是可能的原因分析及解决方案:
动态库中的符号可能由于编译选项或链接器行为导致不可见。例如,某些符号可能被标记为内部符号(static
或 hidden
),从而无法被外部链接。
nm -D /usr/lib/i386-linux-gnu/libtcl8.6.so | grep tclStringType
检查符号是否为动态导出符号。
T
或 D
标志(表示全局符号),说明该符号未被导出。-fvisibility=hidden
并显式导出需要的符号。-fvisibility=hidden
)。链接器对库的解析顺序敏感。如果依赖库的顺序不正确,可能导致未定义引用错误。
-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
即使符号存在于 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
您提到使用的是 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
版本与实际使用的版本一致。tcl8.6
。如果项目中同时使用了静态库和动态库,可能会导致符号冲突或未定义引用。
liboms_shr.so
和 libtcl8.6.so
都是动态库。liboms_shr.so
是静态库,则需要确保其依赖的符号在链接时已完全解析。liboms_shr.so
是静态库,尝试将其改为动态库,或者在链接时显式包含所有依赖的静态库。-O0
)重新编译。根据上述分析,建议按以下步骤排查和解决问题: 1. 确认 libtcl8.6.so
中的符号是否为动态导出符号。 2. 调整链接顺序,确保 -ltcl8.6
在所有依赖它的库之前。 3. 检查动态库路径,确保链接器能够正确找到 libtcl8.6.so
。 4. 排查版本兼容性问题,避免多个版本的 Tcl 库共存。 5. 确认 liboms_shr.so
和 libtcl8.6.so
的类型一致(均为动态库或静态库)。
如果问题仍未解决,请提供更详细的编译日志和环境信息,以便进一步分析。