跳转到内容
新建笔记

GLIBCXX 符号版本与 libstdc++ 加载诊断

这个错误已经到了运行库加载阶段

跳转到“这个错误已经到了运行库加载阶段”

libstdc++.so.6: version 'GLIBCXX_3.4.26' not found 表示某个可执行文件或共享对象要求指定符号版本,而本次实际选中的 libstdc++.so.6 没有满足要求。先从完整错误中找出“由谁要求”和“检查的是哪个库”,不要只看文件名都叫 libstdc++.so.6 就认定兼容。

GLIBCXX_... 是 libstdc++ 的符号版本标签,与 C++11/17/20 语言标准不是一回事。GCC 官方表中,GLIBCXX_3.4.26 随 GCC 9.1.0 系列出现;这不意味着所有 GCC 9 编译的程序都一定要求该标签,也不意味着看到它就能唯一反推发行版包版本。libstdc++ ABI 文档

还要区分 GLIBCXX_...、C++ ABI 的 CXXABI_... 和 glibc 的 GLIBC_...。替换一个满足前者的库,可能又引入目标系统缺少的 glibc 依赖;不能把所有版本字符串都当作同一个库的版本。

原来的 AArch64 与 Conda 记录

跳转到“原来的 AArch64 与 Conda 记录”

原文记录过 /usr/lib/aarch64-linux-gnu/,并提出使用 Conda 安装目录或环境 lib 目录中的 libstdc++.so.6。这些都是特定机器上的候选位置;在 x86-64、其他发行版或不同环境中,路径可以不同。

Conda 的候选库至少要满足下列条件,才能进一步实验:

检查原因
ELF 架构和位数AArch64 不能直接加载 x86-64 的 SO
提供所需的版本化符号仅文件名相同或字符串里出现某标签不够
自身所需的 glibc、libgcc 等依赖新库也可能对系统提出更高要求
程序和插件的 ABI 约定版本标签不能覆盖所有对象布局及编译配置问题
实际加载路径硬盘上“存在一份合适的库”不表示进程选中了它

优先使用同一环境和受支持渠道中匹配的运行库包,或按目标环境重新构建程序。保留现有系统库,把需要的试验局限于应用目录或独立环境;不要用“全局覆盖系统软链接”替代判断。

用自己的最小程序观察需求

跳转到“用自己的最小程序观察需求”

下面的 abi_probe.cpp 使用 C++17 filesystem,只查询当前目录并打印,不修改文件。实际需要哪些符号版本由工具链决定,应读取产物,不能把某台机器的输出硬编码成通用答案。

#include <cstdio>
#include <filesystem>
#include <system_error>
int main()
{
std::error_code error;
const auto directory = std::filesystem::current_path(error);
if (error) {
std::fprintf(stderr, "current_path failed: %s\n", error.message().c_str());
return 1;
}
std::printf("current directory: %s\n", directory.string().c_str());
}

在 Linux shell 中构建并检查自己生成的程序:

终端窗口
g++ -std=c++17 abi_probe.cpp -o abi_probe
readelf -h ./abi_probe
readelf --dynamic ./abi_probe
readelf --version-info ./abi_probe
./abi_probe

分别关注 ELF 机器类型、NEEDED/运行搜索信息,以及版本需求。若错误由插件或某个共享对象引起,也要检查那个对象,不能只检查主程序。readelf 读取文件结构,不需要执行目标程序。GNU readelf

接着查当前编译器会找到的候选库,并读取它的版本定义:

终端窗口
candidate_file=$(g++ -print-file-name=libstdc++.so.6)
readlink -f "$candidate_file"
readelf -h "$candidate_file"
readelf --version-info "$candidate_file"

若编译器只原样输出 libstdc++.so.6,先解决候选文件未定位的问题;不能把它当成已确认的绝对路径。编译器查到的候选也不自动等于某个进程真正加载的文件。

最后检查实际选中的库

跳转到“最后检查实际选中的库”

对上面自己编译、行为已知的探针,可以观察加载器日志:

终端窗口
LD_DEBUG=libs,versions ./abi_probe

该命令会执行程序。日志显示搜索路径、候选文件和版本检查;保存实际选中路径,再对那一份库做检查。不要只取搜索过程里的第一条候选路径就认定它已被加载。Linux 动态加载器调试选项

普通 glibc 环境的加载还受 RPATH/RUNPATH、缓存、默认目录和环境变量影响,某些安全执行模式会忽略环境变量。因此,临时加入目录是诊断手段,不能承诺覆盖所有配置。

若已经检查过候选目录,可对单个命令试验,而不永久改变 shell 或系统配置。下面的路径和程序名必须换成自己的已验证对象:

终端窗口
candidate_dir=/absolute/path/to/verified/environment/lib
LD_LIBRARY_PATH="$candidate_dir${LD_LIBRARY_PATH:+:$LD_LIBRARY_PATH}" ./trusted-app

条件展开避免在原变量为空时意外追加空目录项。成功启动后还应覆盖程序实际功能和插件;仅靠这个目录替换后“不再报第一个错误”不能证明整个环境兼容。

本页在本机 Ubuntu WSL 的 x86-64 GCC 环境中检查正常产物、ELF 版本需求和加载日志。没有复制替换系统运行库,没有更改 Conda 环境,也没有声称重现或解决原 AArch64 机器上的具体故障。