在运行一些编译后的C类二进制程序时,会遇到报错如下:
/lib64/libstdc++.so.6: version `GLIBCXX_3.4.21' not found
这里你就要知道,是你的gcc版本低了,同时你可以检测一下本机所支持的glibc版本范围:
[root@VM-75-61 ~]# strings /usr/lib64/libstdc++.so.6 | grep GLIBC
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
GLIBC_2.2.5
GLIBC_2.3
GLIBC_2.4
GLIBC_2.3.2
GLIBCXX_FORCE_NEW
GLIBCXX_DEBUG_MESSAGE_LENGTH
这里的/usr/lib64/libstdc++.so.6 要用绝对路径,如果找不到就 find。你会发现,报错里面包含的版本确实没有,此时就要考虑升级gcc了~
gcc各版本的下载地址:
目前5.1.0版本的能提供到 GLIBCXX_3.4.21
我们一般下载tar.gz包,下载之后就进行我们的编译过程(以5.1.0为例):
1:tar -zxvf gcc-5.1.0.tar.gz
2:cd gcc-5.1.0
3:./contrib/download_prerequisites
4:cd ../
5:mkdir gcc-build-5.1.0
6:cd gcc-build-5.1.0/
7:../gcc-5.1.0/configure --enable-checking=release --enable-languages=c,c++ --disable-multilib
8:make -j8
9:make install
这个过程,网上说要三个小时左右,但我这里似乎只跑了一个小时~
跑完之后还要进行一些操作,替换原来的软连接到新版本的gcc库上:
1:find / -name libstdc++.so.6*
此时你看到系统下面全部的libstdc++.so.6*,把这个库全部删掉,重新做软连接:
新的库就在刚刚新编译的目录下:
/root/gcc-build-5.1.0/x86_64-unknown-linux-gnu/libstdc++-v3/src/.libs/libstdc++.so.6.0.21
/root/gcc-build-5.1.0/x86_64-unknown-linux-gnu/libstdc++-v3/src/.libs/libstdc++.so.6
/root/gcc-build-5.1.0/stage1-x86_64-unknown-linux-gnu/libstdc++-v3/src/.libs/libstdc++.so.6.0.21
/root/gcc-build-5.1.0/stage1-x86_64-unknown-linux-gnu/libstdc++-v3/src/.libs/libstdc++.so.6
/root/gcc-build-5.1.0/prev-x86_64-unknown-linux-gnu/libstdc++-v3/src/.libs/libstdc++.so.6.0.21
/root/gcc-build-5.1.0/prev-x86_64-unknown-linux-gnu/libstdc++-v3/src/.libs/libstdc++.so.6
把libstdc++.so.6.0.21复制到find出来的目录里,删除原来软连接,重新软连接到libstdc++.so.6.0.21上!
cd gcc-build-5.1.0/
find . -name libstdc++.so.6
ll /usr/lib64/libstdc++.so.6
cp ./prev-x86_64-unknown-linux-gnu/libstdc++-v3/src/.libs/libstdc++.so.6.0.21 /usr/lib64/
rm -rf /usr/lib64/libstdc++.so.6
ln -s libstdc++.so.6.0.21 libstdc++.so.6
ll libstdc++.so.6
strings /usr/lib64/libstdc++.so.6 | grep GLIBCXX_3
这里共享库升级好了之后,可以先测试下gcc的版本:
gcc -v
如果还是之前的老版本的话,那么就是二进制文件的更新问题了:
[root@Vm-75-60 gcc-build-5.1.0]# find / -type f -name gcc
/usr/local/bin/gcc
/usr/bin/gcc
这里,/usr/local下的是新安装的gcc命令,此时把原来的/usr/bin/gcc bak掉
cp /usr/local/bin/gcc /usr/bin/gcc
此时再次执行:
[root@Vm-75-60 gcc-build-5.1.0]# gcc -v
Using built-in specs.
COLLECT_GCC=gcc
COLLECT_LTO_WRAPPER=/usr/local/libexec/gcc/x86_64-unknown-linux-gnu/5.1.0/lto-wrapper
Target: x86_64-unknown-linux-gnu
Configured with: ../gcc-5.1.0/configure --enable-checking=release --enable-languages=c,c++ --disable-multilib
Thread model: posix
gcc version 5.1.0 (GCC)
ok,升级到5.1了!
这里需要注意的是,如果有编译需求的话,是走g++的,这里看下:
[root@Vm-75-60 ~]# g++ -v
Using built-in specs.
Target: x86_64-redhat-linux
Configured with: ../configure --prefix=/usr --mandir=/usr/share/man --infodir=/usr/share/info --with-bugurl=http://bugzilla.redhat.com/bugzilla --enable-bootstrap --enable-shared --enable-threads=posix --enable-checking=release --with-system-zlib --enable-__cxa_atexit --disable-libunwind-exceptions --enable-gnu-unique-object --enable-languages=c,c++,objc,obj-c++,java,fortran,ada --enable-java-awt=gtk --disable-dssi --with-java-home=/usr/lib/jvm/java-1.5.0-gcj-1.5.0.0/jre --enable-libgcj-multifile --enable-java-maintainer-mode --with-ecj-jar=/usr/share/java/eclipse-ecj.jar --disable-libjava-multilib --with-ppl --with-cloog --with-tune=generic --with-arch_32=i686 --build=x86_64-redhat-linux
Thread model: posix
gcc version 4.4.7 20120313 (Red Hat 4.4.7-23) (GCC)
很奇怪,g++还是老版本,操作步骤同上,再执行一遍g++
gcc的编译包中也会包含g++的二进制,find一下就即可:
[root@Vm-75-60 ~]# find / -name g++
/usr/local/bin/g++
/usr/bin/g++
[root@Vm-75-60 ~]# mv /usr/bin/g++ /usr/bin/g++_bak
[root@Vm-75-60 ~]# cp /usr/local/bin/g++ /usr/bin/g++
[root@Vm-75-60 ~]# g++ -v
Using built-in specs.
COLLECT_GCC=g++
COLLECT_LTO_WRAPPER=/usr/local/libexec/gcc/x86_64-unknown-linux-gnu/5.1.0/lto-wrapper
Target: x86_64-unknown-linux-gnu
Configured with: ../gcc-5.1.0/configure --enable-checking=release --enable-languages=c,c++ --disable-multilib
Thread model: posix
gcc version 5.1.0 (GCC)
OK,这里就正常升级了!
[root@VM_13_117_centos ~]# gcc -v
Using built-in specs.
COLLECT_GCC=gcc
COLLECT_LTO_WRAPPER=/usr/local/libexec/gcc/x86_64-unknown-linux-gnu/5.1.0/lto-wrapper
Target: x86_64-unknown-linux-gnu
Configured with: ../gcc-5.1.0/configure --enable-checking=release --enable-languages=c,c++ --disable-multilib
Thread model: posix
gcc version 5.1.0 (GCC)
你会发现已经变成5.1了,同时,再执行之前的strings指令:
[root@VM_13_117_centos ~]# strings /usr/lib64/libstdc++.so.6 | grep GLIBC
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
GLIBC_2.3
GLIBC_2.2.5
GLIBC_2.3.2
GLIBCXX_FORCE_NEW
GLIBCXX_DEBUG_MESSAGE_LENGTH
现在最高就到GLIBCXX_3.4.21,同时原先的程序就也能开起来了!
注意:这里需要注意,开发环境和线上环境的完全一致性,尤其是c类的程序编译过程中的参数选择问题,使用满足陈旭运行的共享库版本即可,而不是一味追求高版本,笔者上面的问题就是因为开发擅自修改了编译参数,导致编译后的二进制在6系和7系自带的gcc环境下没法运行,必须升级,而升级gcc又是比较麻烦的事情,后面找到问题,改回参数,就不存在上面报错的问题了!
以上,共勉!