如需转载请标明出处:http://blog.csdn.net/itas109
QQ技术交流群:129518033
相关问题:
1.glibc不兼容
2. /lib64/libstdc++.so.6: version `GLIBCXX_3.4.21’ not found
3. 跨操作系统应用程序
相关阅读:
Windows/Linux链接器加载动态库的搜索路径顺序
gcc link链接常用选项及应用
环境:
OS : deepIn 15.11/Centos 7
编译器: g++ 6.3.0/g++ 4.8.5
开发环境为gcc 6.3.0,但是生产环境glibc版本为4.8.5,这种情况下该怎么运行程序呢?
本文将以一个例子来介绍如何解决这种不同版本glibc的问题。有如下几种方式:
$ ldd --version
ldd (Debian GLIBC 2.24-11+deb9u3) 2.24
$ ldd --version
ldd (GNU libc) 2.17
$ strings /usr/lib64/libstdc++.so.6 | grep GLIBCXX
GLIBCXX_3.4
GLIBCXX_3.4.1
...
GLIBCXX_3.4.22
GLIBCXX_DEBUG_MESSAGE_LENGTH
$ strings /usr/lib64/libstdc++.so.6 | grep GLIBCXX
GLIBCXX_3.4
GLIBCXX_3.4.1
...
GLIBCXX_3.4.19
GLIBCXX_DEBUG_MESSAGE_LENGTH
注意:本程序在gcc 4.8.5的环境无法正常运行
https://stackoverflow.com/questions/12530406/is-gcc-4-8-or-earlier-buggy-about-regular-expressions
//regex.cpp
#include
#include
using namespace std;
int main()
{
// gcc 4.8.5 run error
std::regex m_regex("[a-z]+");
std::cout << std::regex_match("abc", m_regex) << std::endl;
return 0;
}
g++ 6.3.0
$ g++ -o regex regex.cpp
$ ldd regex
linux-vdso.so.1 (0x00007fff087f9000)
libstdc++.so.6 => /lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007fdeb0b41000)
libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007fdeb083d000)
libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007fdeb0626000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fdeb0287000)
/lib64/ld-linux-x86-64.so.2 (0x00007fdeb1103000)
$ du -h regex
508K regex
$ ./regex
1
使用g++ 6.3.0直接编译的程序,在g++ 4.8.5的环境上运行会报错
g++ 4.8.5
$ ldd regex
./regex: /lib64/libstdc++.so.6: version `CXXABI_1.3.9' not found (required by ./regex)
./regex: /lib64/libstdc++.so.6: version `GLIBCXX_3.4.21' not found (required by ./regex)
linux-vdso.so.1 => (0x00007ffff05d7000)
libstdc++.so.6 => /lib64/libstdc++.so.6 (0x00007f1d59c9b000)
libm.so.6 => /lib64/libm.so.6 (0x00007f1d59999000)
libgcc_s.so.1 => /lib64/libgcc_s.so.1 (0x00007f1d59783000)
libc.so.6 => /lib64/libc.so.6 (0x00007f1d593b6000)
/lib64/ld-linux-x86-64.so.2 (0x00007f1d5a1e2000)
$ ./regex
./regex: /lib64/libstdc++.so.6: version `CXXABI_1.3.9' not found (required by ./regex)
./regex: /lib64/libstdc++.so.6: version `GLIBCXX_3.4.21' not found (required by ./regex)
g++ 6.3.0的开发环境上:
编写拷贝动态库的shell脚本copylib.sh
#!/bin/bash
# copylib.sh
LibDir=$PWD"/lib"
Target=$1
lib_array=($(ldd $Target | grep -o "/.*" | grep -o "/.*/[^[:space:]]*"))
$(mkdir $LibDir)
for Variable in ${lib_array[@]}
do
cp "$Variable" $LibDir
done
./copylib.sh regex
$ tree
.
├── cplib.sh
├── lib
│ ├── ld-linux-x86-64.so.2
│ ├── libc.so.6
│ ├── libgcc_s.so.1
│ ├── libm.so.6
│ └── libstdc++.so.6
└── regex
g++ 4.8.5的生产环境上:
源码编译patchelf
git clone https://github.com/NixOS/patchelf.git
./bootstrap.sh
./configure
make
sudo make install
查看patchelf版本
$ patchelf --version
patchelf 0.11
修改可执行程序的动态库搜索路径rpath和动态库加载器dynamic loader (“ELF interpreter”)
patchelf --set-rpath `pwd`/lib regex
patchelf --set-interpreter `pwd`/lib/ld-linux-x86-64.so.2 regex
$ ldd regex
linux-vdso.so.1 => (0x00007ffd12ddd000)
libstdc++.so.6 => /home/dev1/regex/pack/lib/libstdc++.so.6 (0x00007f6b30f1b000)
libm.so.6 => /home/dev1/regex/pack/lib/libm.so.6 (0x00007f6b30c17000)
libgcc_s.so.1 => /home/dev1/regex/pack/lib/libgcc_s.so.1 (0x00007f6b30a00000)
libc.so.6 => /home/dev1/regex/pack/lib/libc.so.6 (0x00007f6b30661000)
/home/dev1/regex/pack/lib/ld-linux-x86-64.so.2 => /lib64/ld-linux-x86-64.so.2 (0x00007f6b314e0000)
执行程序
$ ./regex
1
特别说明:
答案是肯定的。
动态库加载器dynamic loader(“ELF interpreter”),程序启动时,操作系统会把控制权转交给ld-linux-x86-64.so.2,而不是交给程序正常的进入地址,ld-linux-x86-64.so.2会寻找并加载所有需要的库文件,然后再将控制权交给应用的起始入口。
经过查看文件头,可以看出ld-linux-x86-64.so.2的位置信息写死在ELF中,并不受rpath和LD_LIBRARY_PATH的影响。
$ readelf -l regex
Elf 文件类型为 DYN (共享目标文件)
入口点 0x44b0
共有 9 个程序头,开始于偏移量64
程序头:
Type Offset VirtAddr PhysAddr
...
[Requesting program interpreter: /lib64/ld-linux-x86-64.so.2]
...
这里可以通过
方式1:(有源码,指定ld-linux-x86-64.so.2的路径)
g++ -o regex regex.cpp -Wl,-dynamic-linker='./lib/ld-linux-x86-64.so.2'
方式2:(无源码,通过patchelf修改elf中ld-linux-x86-64.so.2路径)
patchelf --set-interpreter `pwd`/lib/ld-linux-x86-64.so.2 regex
答案是否定的
可以通过LD_LIBRARY_PATH设置搜索路径
export LD_LIBRARY_PATH=`pwd`/lib:$LD_LIBRARY_PATH
./regex
查看程序elf动态库信息
$ readelf -d regex
Dynamic section at offset 0x80000 contains 30 entries:
标记 类型 名称/值
0x000000000000001d (RUNPATH) Library runpath: [/home/dev1/regex/lib]
0x0000000000000001 (NEEDED) 共享库:[libstdc++.so.6]
0x0000000000000001 (NEEDED) 共享库:[libm.so.6]
0x0000000000000001 (NEEDED) 共享库:[libgcc_s.so.1]
0x0000000000000001 (NEEDED) 共享库:[libc.so.6]
...
注意:准确说应该是半静态编译,真正静态编译选项为-static
g++ 6.3.0
$ g++ -o regex regex.cpp -static-libgcc -static-libstdc++
$ ldd regex
linux-vdso.so.1 (0x00007ffc627db000)
libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f57f4985000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f57f45e6000)
/lib64/ld-linux-x86-64.so.2 (0x00007f57f4fbd000)
$ du -h regex
1.8M regex
$ ./regex
1
g++ 4.8.5
$ ldd regex
linux-vdso.so.1 => (0x00007ffd67757000)
libm.so.6 => /lib64/libm.so.6 (0x00007f60167ec000)
libc.so.6 => /lib64/libc.so.6 (0x00007f601641f000)
/lib64/ld-linux-x86-64.so.2 (0x00007f6016e22000)
$ ./regex
1
docker容器是一种解决方式,但是由于其需要先安装docker,所以不太建议使用该方式。
该方式虽然可以解决问题,但是在生产环境中该方式风险极大,所以极不推荐使用该方式。
License
License under CC BY-NC-ND 4.0: 署名-非商业使用-禁止演绎
如需转载请标明出处:http://blog.csdn.net/itas109
QQ技术交流群:129518033
Reference:
NULL