在運行一些編譯后的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又是比較麻煩的事情,后面找到問題,改回參數,就不存在上面報錯的問題了!
以上,共勉!