关于gcc中遇到的问题,这里有你想要的全部答案
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
关于gcc中遇到的问题,这里有你想要的全部答案
前言
什么是 gcc
[gcc 官方网站](/)
GCC(GNU Compiler Collection,GNU编译器套件),是由GNU 开发的编程语言编译器。
它是以GPL(General Public License)许可证所发行的自由软件,也是GNU 计划的关键部分(GPU 是一个软件工程项目,是 GNU's Not Unix 的缩写)。
GCC 原本作为GNU 操作系统的官方编译器,现已被大多数类Unix 操作系统(如Linux、BSD、Mac OS X等)采纳为标准的编译器,GCC 同样适用于微软的Windows。
GCC 是自由软件过程发展中的著名例子,由自由软件基金会以 GPL 协议发布。
什么是 glibc
[glibc 官方网站](
/software/libc/)
glibc 是 gnu 发布的 libc 库,即 c 运行库。
glibc 是 linux 系统中最底层的 api,几乎其他任何的运行库都会依赖 glibc. glibc 除了封装linux 操作系统所提供的系统服务外,它本身提供了许多其它一些必要服务的实现,主要有:
•string:字符串处理
•signal:信号处理
•dlfcn:管理共享库的动态加载
•direct:文件目录操作
•elf:共享库的动态加载器,即 interpreter
•iconv:不同字符集的编码转换
•inet:socket 接口的实现
•intl:gettext 的实现
•io
•linuxthreads
•locale:本地化
•login:虚拟终端设备的管理,及系统的安全访问
•malloc:动态内存管理的分配与管理
•nis
•stdlib
•math
gcc 和 glibc 的关系
首先,gcc 是编译器,基本上 linux 下所有程序(包括内核)都是gcc 编译的,libc 也是。
但 gcc 和 libc 又是相互依赖的,什么意思呢?就是在编译 c/cpp 代码时,既需要 gcc,也需要 libc.
gcc 发行版本
截止2021年8月,最新版本已经到 gcc11.2 了。
glibc 发行版本
截止2021年8月,最新版本已经到glibc2.34 了,历史版本有glibc2.29、2.30、2.31、2.32、2.33 等。
查看命令
1、查看当前系统的 glibc 版本
•方法1:
/lib/x86_64-linux-gnu/libc.so.6
为什么这个库可以直接运行呢?原来是在libc 的代码中有一点小手脚:
void__libc_main (void) { __libc_print_version (); _exit (0); } •方法2:
ldd 命令也是 glibc 提供的,所以也能查看 glibc 版本:
ldd --version
2、查看 glibc 的 api 版本
strings /lib/x86_64-linux-gnu/libc.so.6 | grep GLIBC
3、查看 so 信息
`objdump -p test_gcc.so`,其他类似命令还有 `nm` 和 `readelf`
4、查看当前so依赖哪些so
•方法1:
`ldd test_gcc.so`
•方法2:
`objdump -x test_gcc.so | grep NEEDED`
5、获取 gcc 依赖的某个 so 文件位置
`gcc --print-file-name=libz.so.1`
6、查看当前使用的 gcc 版本和引用的头文件路径
`echo | gcc -v -x c -E -`
7、查看当前so使用了GLIBC_2.23中哪些函数
`objdump -T test_gcc.so | grep GLIBC_2.23`
8、查看当前so使用的memcpy版本
`nm test_gcc.so | grep memcpy -w``objdump -T /lib/x86_64-linux-gnu/libc.so.6 | grep memcpy`
9、设置 c、c++ 头文件路径
`export CPLUS_INCLUDE_PATH=/opt/compiler/gcc-8.2/x86_64-custom-linux-
gnu/include/c++/8.2.0:/usr/include/x86_64-linux-gnu/``export
C_INCLUDE_PATH=......`
10、编译时如何设置链接器版本
指定正确的 ldd 路径,也就是对应具体的 glibc 版本(非常重要)。
11、设置链接库路径
•方法1:
先查看:`echo $LD_LIBRARY_PATH`,可通过该环境变量直接设置。
或者,`gcc --print-search-dirs`
•方法2:使用动态库管理命令 ldconfig
`ldconfig -v`: 查看所有动态链接库
`vim /etc/ld.so.conf`,显示`include /etc/ld.so.conf.d/*.conf`,
然后`cd /etc/ld.so.conf.d`
修改完之后,要重新运行下 `ldconfig`
解释:
linux 下的共享库机制采用了类似于高速缓存的机制,将库信息保存在`/etc/ld.so.cache`里边。
程序连接的时候首先从这个文件里边查找,然后再到`ld.so.conf`的路径里边去详细找。
这就是为什么修改了`ld.so.conf`要重新运行一下`ldconfig`的原因12、c++ 标准库: stdlibc++ 和 libc 的版本号是不一样的
`objdump -T /usr/lib/gcc/x86_64-linux-gnu/5/libstdc++.so | grep GLIBCXX`
13、gcc 头文件的搜索路径顺序
1. 优先搜索`-I`指定的路径
2. 查找GCC的环境变量`C_INCLUDE_PATH`/`CPLUS_INCLUDE_PATH`/`OBJC_INCLUDE_PA TH`指定的路径
3. 查找默认的搜索路径`/usr/include`、`/usr/local/include`
14、gcc搜索链接库(编译期 + 运行期)的顺序
gcc在编译时按照如下顺序寻找所需要的库文件:
1. gcc会去找`-L`指定的目录
2. 再找gcc的环境变量`LIBRARY_PATH`
3. 再找内定目录
•/lib和/lib64
•/usr/lib 和/usr/lib64
•/usr/local/lib和/usr/local/lib64
这是当初 compile gcc 时写在程序内的。
这里有两个问题:
•默认情况下,gcc编译时只会查找相应的头文件,而不会连接具体的lib。
也就是说只要include设置完全,就可以编译通过。
它没有进一步检查include中的类和函数有没有实现,而是在运行时才开始查
找。
所以就会经常发生编译可以通过,但运行时却无法运行,因为在运行时它找不到相关类或者函数的实现。
这时,使用`-Wl`,`--no-undefined`参数,如果使用了 include 文件,链接器却找不到相应的实现,就会产生错误提示。
•编译时默认不查找当前目录,需要使用`-L ./`指定,例如
运行时动态库的搜索路径的先后顺序是:
1. 编译目标代码时指定的动态库搜索路径;这是通过gcc的参数`-Wl,-rpath=`指定。
当指定多个动态库搜索路径时,路径之间用冒号:分隔
2. 环境变量`LD_LIBRARY_PATH`指定的动态库搜索路径
3. 配置文件`/etc/ld.so.conf`中指定的动态库搜索路径
4. 默认的动态库搜索路径,如:`/lib`, `/usr/lib`
注意:
1. 动态库搜寻路径并不包括当前目录,所以当即使可执行文件和其所需的so文件在同一文件夹,也会出现找不到问题
2. 一般不推荐直接修改环境变量,而是修改`/etc/ld.so.conf`,将相应的路径添加上,然后`ldconfig`一下就好
3. ldconfig做的这些东西都与运行程序时有关,跟编译时一点关系都没有,编译的时候还是该加`-L`就得加,不要混淆了
4. 往`/lib`和`/usr/lib`里面加 `lib`,是不用修改`/etc/ld.so.conf`的,但是完了之后要调一下`ldconfig`(很重要),不然这个`lib`会找不到。
而往其他目录加`lib`,需要修改`/etc/ld.so.conf`,并且要`ldconfig`一下。
15、如何安装指定版本glibc
•从官网下载,解压,如 ./glibc-2.21
•cd glibc-2.21
•mkdir build
•mkdir /opt/glibc-2.21
•cd build
•../configure --prefix=/opt/glibc-2.21
•apt-get install gawk
•make
•需要解决一些编译告警或错误问题
•报错(解决):./stdlib/setenv.c +270 •报错(未解决):
../sysdeps/x86_64/multiarch/strstr.c:47:30 •未完待续。