Linux 解决 libstdc++ 的版本问题

错误日志信息

1
/usr/lib64/libstdc++.so.6: version 'GLIBCXX_3.4.21' not found

系统环境

1
2
CentOS Linux release 7.6.1810 (Core)
Linux centos7 3.10.0-957.5.1.el7.x86_64 #1 SMP Fri Feb 1 14:54:57 UTC 2019 x86_64 x86_64 x86_64 GNU/Linux

查看当前 libstdc++(GLIBCXX)的版本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# strings /usr/lib64/libstdc++.so.6 | grep GLIBCXX
GLIBCXX_3.4
GLIBCXX_3.4.1
GLIBCXX_3.4.2
GLIBCXX_3.4.3
GLIBCXX_3.4.4
GLIBCXX_3.4.5
GLIBCXX_3.4.6
GLIBCXX_3.4.7
GLIBCXX_3.4.8
GLIBCXX_3.4.9
GLIBCXX_3.4.10
GLIBCXX_3.4.11
GLIBCXX_3.4.12
GLIBCXX_3.4.13
GLIBCXX_3.4.14
GLIBCXX_3.4.15
GLIBCXX_3.4.16
GLIBCXX_3.4.17
GLIBCXX_3.4.18
GLIBCXX_3.4.19

可以发现当前系统最高只支持 GLIBCXX_3.4.19,并不支持 GLIBCXX_3.4.21,因此当安装需要依赖 GLIBCXX_3.4.21 的软件时,就会出现 /usr/lib64/libstdc++.so.6: version 'GLIBCXX_3.4.21' not found 的错误。

查找 libstdc++.so.6.0.21 库文件

1
2
3
4
5
# 查找库文件
# find / -name libstdc++.so.6.0.21

# 如果libstdc++.so.6.0.21库文件已存在,则按照下面的步骤直接创建软链接即可
# 如果libstdc++.so.6.0.21库文件不存在,则需要按照下面的步骤编译新版本的GCC,然后再创建软链接

编译新版本的 GCC

GCC 各版本的下载地址在这里,其中 gcc-5.2.0 对应 GLIBCXX_3.4.21libstdc++.so.6.0.21,而 gcc-6.5.0 对应 GLIBCXX_3.4.22libstdc++.so.6.0.22,根据自己的需要下载对应版本的 GCC 即可。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# 下载文件(117M)
# wget http://ftp.tsukuba.wide.ad.jp/software/gcc/releases/gcc-5.2.0/gcc-5.2.0.tar.bz2

# 解压文件
# tar -xvf gcc-5.2.0.tar.bz2

# 进入解压目录
# cd gcc-5.2.0

# 下载编译gcc所需的依赖文件和库
# ./contrib/download_prerequisites

# 建立输出目录,用于存放编译时所有产生的中间文件
# mkdir build

# 进入输出目录
# cd build

# 执行configure配置
# ../configure --enable-checking=release --enable-languages=c,c++ --disable-multilib

# 编译gcc,指定编译使用的线程数为8,编译耗时较长,可能需要几个小时
# make -j8

# 这里为了避免影响系统的稳定性,暂时不执行"make install"命令来替换系统默认版本的gcc

建立软链接

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
# 进入输出目录
# cd build

# 查找编译生成libstdc++.so库文件,下面查找到的libstdc++.so、libstdc++.so.6都只是软链接文件,libstdc++.so.6.0.21才是真正编译生成的库文件
# find . -name "libstdc++.so*"
./prev-x86_64-unknown-linux-gnu/libstdc++-v3/src/.libs/libstdc++.so
./prev-x86_64-unknown-linux-gnu/libstdc++-v3/src/.libs/libstdc++.so.6
./prev-x86_64-unknown-linux-gnu/libstdc++-v3/src/.libs/libstdc++.so.6.0.21
./stage1-x86_64-unknown-linux-gnu/libstdc++-v3/src/.libs/libstdc++.so
./stage1-x86_64-unknown-linux-gnu/libstdc++-v3/src/.libs/libstdc++.so.6
./stage1-x86_64-unknown-linux-gnu/libstdc++-v3/src/.libs/libstdc++.so.6.0.21
./x86_64-unknown-linux-gnu/libstdc++-v3/src/.libs/libstdc++.so
./x86_64-unknown-linux-gnu/libstdc++-v3/src/.libs/libstdc++.so.6
./x86_64-unknown-linux-gnu/libstdc++-v3/src/.libs/libstdc++.so.6.0.21

# 拷贝libstdc++.so.6.0.21库文件到/usr/lib64/目录下
# cp ./x86_64-unknown-linux-gnu/libstdc++-v3/src/.libs/libstdc++.so.6.0.21 /usr/lib64

# 备份系统原有的libstdc++.so.6链接文件
# cp /usr/lib64/libstdc++.so.6 /usr/lib64/libstdc++.so.6.bak

# 覆盖系统原有的libstdc++.so.6链接文件(这里尽量不要先删除旧的再创建新的libstdc++.so.6链接文件)
# ln -s -f /usr/lib64/libstdc++.so.6.0.21 /usr/lib64/libstdc++.so.6

# 进入lib64目录
# cd /usr/lib64

# 查看最终的libstdc++.so库文件列表
# ls -al /usr/lib64/libstdc++.so.6*
lrwxrwxrwx. 1 root root 19 3月 12 10:08 /usr/lib64/libstdc++.so.6 -> libstdc++.so.6.0.21
-rwxr-xr-x. 1 root root 991616 10月 30 14:39 /usr/lib64/libstdc++.so.6.0.19
-rwxr-xr-x. 1 root root 11485880 3月 12 10:01 /usr/lib64/libstdc++.so.6.0.21

验证新的 libstdc++.so.6.0.21 库文件是否生效

如果在下面的输出结果中,出现 GLIBCXX_3.4.21,则代表新的 libstdc++.so.6.0.21 库文件生效了。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# strings /usr/lib64/libstdc++.so.6 | grep GLIBCXX
GLIBCXX_3.4
GLIBCXX_3.4.1
GLIBCXX_3.4.2
GLIBCXX_3.4.3
GLIBCXX_3.4.4
GLIBCXX_3.4.5
GLIBCXX_3.4.6
GLIBCXX_3.4.7
GLIBCXX_3.4.8
GLIBCXX_3.4.9
GLIBCXX_3.4.10
GLIBCXX_3.4.11
GLIBCXX_3.4.12
GLIBCXX_3.4.13
GLIBCXX_3.4.14
GLIBCXX_3.4.15
GLIBCXX_3.4.16
GLIBCXX_3.4.17
GLIBCXX_3.4.18
GLIBCXX_3.4.19
GLIBCXX_3.4.20
GLIBCXX_3.4.21

参考文章