分享

关于 gcc 中遇到的问题,这里有你想要的全部答案

 菌心说 2022-01-14

前言

什么是 gcc

[gcc 官方网站](https://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 官方网站](
https://www./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_PATH`指定的路径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

  • 未完待续。。。

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多