不同Ubuntu机器glog符号不一致及链接失败问题咨询
问题描述
初始问题:不同Ubuntu机器上glog库符号缺失
我通过Bazel导入glog库,Workspace配置如下:
def glog_workspace(): http_archive( name = "com_google_glog", sha256 = "8a83bf982f37bb70825df71a9709fa90ea9f4447fb3c099e1d720a439d88bad6", strip_prefix = "glog-0.6.0/", urls = ["https://github.com/google/glog/archive/v0.6.0.tar.gz"], )
我需要调用内部函数google::glog_internal_namespace_::DumpStackTraceToString(std::string)获取可读堆栈信息,但在两台Ubuntu机器上出现差异:
第一台机器系统信息:
$ uname -a Linux <hostname> 5.8.0-59-generic #66~20.04.1-Ubuntu SMP Thu Jun 17 11:14:10 UTC 2021 x86_64 x86_64 x86_64 GNU/Linux
该机器的libglog.so包含目标符号:
$ nm -C bazel-out//k8-fastbuild/bin/external/com_google_glog/libglog.so | grep Dump 000000000002c350 t google::(anonymous namespace)::DumpTimeInfo() 000000000002c600 t google::(anonymous namespace)::DumpSignalInfo(int, siginfo_t*) 000000000002c490 t google::(anonymous namespace)::DumpStackFrameInfo(char const*, void*) 000000000002f070 T google::glog_internal_namespace_::DumpStackTraceToString(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >*) 000000000002f0a0 t google::DumpStackTrace(int, void (*)(char const*, void*), void*) 000000000002f670 t google::DumpPCAndSymbol(void (*)(char const*, void*), void*, void*, char const*) 000000000002f350 t google::DumpStackTraceAndExit() 000000000002f770 t google::DumpPC(void (*)(char const*, void*), void*, void*, char const*)
第二台机器系统信息:
$ uname -a Linux <hostname> 5.4.0-77-generic #86-Ubuntu SMP Thu Jun 17 11:14:10 UTC 2021 x86_64 x86_64 x86_64 GNU/Linux
但这台机器的libglog.so中找不到目标符号,导致链接失败:
$ nm -C bazel-out//k8-fastbuild/bin/external/com_google_glog/libglog.so | grep Dump 0000000000022fc0 t google::(anonymous namespace)::DumpTimeInfo() 0000000000023110 t google::(anonymous namespace)::DumpStackFrameInfo(char const*, void*)
想知道这是什么原因?
更新问题:符号存在但链接失败
手动启用相关函数后,出现新的链接错误:
ubuntu@hao:~/ghost-playground$ bazel build //base:logging_test INFO: Writing tracer profile to '/home/ubuntu/.cache/bazel/_bazel_ubuntu/212e06aedd435bfcd4b0defa3d42f92f/command.profile.gz' INFO: Analyzed target //base:logging_test (0 packages loaded, 5 targets configured). INFO: Found 1 target... ERROR: /home/ubuntu/ghost-playground/base/BUILD:28:1: Linking of rule '//base:logging_test' failed (Exit 1) clang failed: error executing command /usr/bin/clang @bazel-out/k8-fastbuild/bin/base/logging_test-2.params Use --sandbox_debug to see verbose messages from the sandbox bazel-out/k8-fastbuild/bin/_solib_k8/libbase_Sliblogging.so: error: undefined reference to 'google::glog_internal_namespace_::DumpStackTraceToString(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >*)' clang: error: linker command failed with exit code 1 (use -v to see invocation) Target //base:logging_test failed to build Use --verbose_failures to see the command lines of failed build steps. INFO: Elapsed time: 0.255s, Critical Path: 0.08s INFO: 0 processes. FAILED: Build did NOT complete successfully
但检查符号发现该函数确实存在:
ubuntu@hao:~/ghost-playground$ nm -C bazel-out/k8-fastbuild/bin/external/com_google_glog/libglog.so | grep DumpStackTraceToString 0000000000026230 t google::glog_internal_namespace_::DumpStackTraceToString(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >*)
明明符号存在,为什么还是链接失败?
解答
一、不同机器符号缺失的原因
- 编译宏控制:glog的堆栈相关函数由
GOOGLE_GLOG_HAVE_STACKTRACE宏控制编译,该宏是否生效取决于系统是否提供堆栈回溯依赖(如libunwind库或execinfo.h头文件)。第二台机器可能缺少这些依赖,导致编译时跳过了相关函数的生成。 - 工具链差异:两台机器的Bazel版本、默认编译工具链(GCC/Clang版本)不同,可能触发glog的不同编译分支。旧版本工具链可能无法正确检测到系统的堆栈回溯支持,从而未启用对应功能。
- 系统依赖缺失:Ubuntu 5.4内核对应的系统包中,可能未预装
libunwind-dev或libexecinfo-dev,而5.8内核的机器默认包含这些依赖,因此glog编译时启用了堆栈功能。
二、符号存在但链接失败的原因
看nm输出的符号前缀:t表示该符号是本地(static)符号,仅在编译它的目标文件内部可见;而外部模块能引用的是全局符号(前缀为T)。
出现这个情况的原因:
- 你手动启用函数时,可能仅在glog的某个源文件中开启了编译,但该函数被声明为
static,导致符号无法导出到动态库的全局符号表中。 - glog的内部命名空间函数设计上就是不对外暴露的,即使通过宏强制编译,也会被限制为本地符号,无法被外部代码链接调用。
内容的提问来源于stack exchange,提问作者Tinyden
相关产品推荐
相关产品推荐

