为啥各种系统库的头文件都找不到

为啥各种系统库的头文件都找不到,第1张

头文件:1. #include “headfile.h”搜索顺序为:①先搜索当前目录②然后搜索-I指定的目录③再搜索gcc的环境变量CPLUS_INCLUDE_PATH(C程序使用的是C_INCLUDE_PATH)④最后搜索gcc的内定目录/usr/include/usr/local/include/usr/lib/gcc/x86_64-redhat-linux/4.1.1/include 各目录存在相同文件时,先找到哪个使用哪个。2. #include <headfile.h>①先搜索-I指定的目录②然后搜索gcc的环境变量CPLUS_INCLUDE_PATH③最后搜索gcc的内定目录/usr/include/usr/local/include/usr/lib/gcc/x86_64-redhat-linux/4.1.1/include 与上面的相同,各目录存在相同文件时,先找到哪个使用哪个。这里要注意,#include<>方式不会搜索当前目录! 这里要说下include的内定目录,它不是由$PATH环境变量指定的,而是由g++的配置prefix指定的(知道它在安装g++时可以指定,不知安装后如何修改的,可能是修改配置文件,需要时再研究下):-bash-3.2$ g++ -vUsing built-in specs.Target: x86_64-redhat-linuxConfigured with: ../configure --prefix=/usr --mandir=/usr/share/man --infodir=/usr/share/info --enable-shared --enable-threads=posix --enable-checking=release --with-system-zlib --enable-__cxa_atexit --disable-libunwind-exceptions --enable-libgcj-multifile --enable-languages=c,c++,objc,obj-c++,java,fortran,ada --enable-java-awt=gtk --disable-dssi --enable-plugin --with-java-home=/usr/lib/jvm/java-1.4.2-gcj-1.4.2.0/jre --with-cpu=generic --host=x86_64-redhat-linuxThread model: posixgcc version 4.1.2 20080704 (Red Hat 4.1.2-46) 在安装g++时,指定了prefix,那么内定搜索目录就是:Prefix/includePrefix/local/includePrefix/lib/gcc/--host/--version/include编译时可以通过-nostdinc++选项屏蔽对内定目录搜索头文件。 库文件:编译的时候:①gcc会去找-L②再找gcc的环境变量LIBRARY_PATH③再找内定目录 /lib /usr/lib /usr/local/lib 这是当初compile gcc时写在程序内的(不可配置的?) 运行时动态库的搜索路径:动态库的搜索路径搜索的先后顺序是:①编译目标代码时指定的动态库搜索路径(这是通过gcc 的参数"-Wl,-rpath,"指定。当指定多个动态库搜索路径时,路径之间用冒号":"分隔)②环境变量LD_LIBRARY_PATH指定的动态库搜索路径(当通过该环境变量指定多个动态库搜索路径时,路径之间用冒号":"分隔)③配置文件/etc/ld.so.conf中指定的动态库搜索路径;④默认的动态库搜索路径/lib;⑤默认的动态库搜索路径/usr/lib。(应注意动态库搜寻路径并不包括当前文件夹,所以当即使可执行文件和其所需的so文件在同一文件夹,也会出现找不到so的问题,类同#include <header_file>不搜索当前目录)

修改它的环境变量试试,下面是有关文章,你看看。

gcc环境变量

1.运行时动态库的搜索路径

方法一:在配置文件/etc/ld.so.conf中指定动态库搜索路径

方法二:通过环境变量LD_LIBRARY_PATH指定动态库搜索路径(当通过该环境变量指定多个动态库搜索路径时,路径之间用冒号":"分隔)

方法三:在编译目标代码时指定该程序的动态库搜索路径(还可以在编译目标代码时指定程序的动态库搜索路径.

这是通过gcc 的参数"-Wl,-rpath,"指定(如例3所示).当指定多个动态库搜索路径时,路径之间用冒号":"分隔)

四:默认的动态库搜索路径/lib

五:默认的动态库搜索路径/usr/lib

动态库的搜索路径搜索的先后顺序是:

(1).编译目标代码时指定的动态库搜索路径;

(2).环境变量LD_LIBRARY_PATH指定的动态库搜索路径;

(3).配置文件/etc/ld.so.conf中指定的动态库搜索路径;

(4).默认的动态库搜索路径/lib;

(5).默认的动态库搜索路径/usr/lib.

2※预处理(preprocessing),编译(compilation),汇编(assembly)和连接(linking)

※include的header文件,连结数据库,系统定义,总共有下列来源指定gcc去那找.

当初在编译时指定的(在~gcc/gcc/collect2.c:locatelib()

写在specs内的

后来用-D -I -L指定的

gcc环境变量设定(编译的时候)

ld.so的环境变量(这是run time的时候)

===========================================

1

===========================================

1.头文件

gcc 在编译时如何去寻找所需要的头文件 :

※所以header file的搜寻会从-I开始

※然后找gcc的环境变量 C_INCLUDE_PATH,CPLUS_INCLUDE_PATH,OBJC_INCLUDE_PATH

※再找内定目录

/usr/include

/usr/local/include

/usr/lib/gcc-lib/i386-linux/2.95.2/include

/usr/lib/gcc-lib/i386-linux/2.95.2/../../../../include/g++-3

/usr/lib/gcc-lib/i386-linux/2.95.2/../../../../i386-linux/include

库文件但是如果装gcc的时候,是有给定的prefix的话,那么就是

/usr/include

prefix/include

prefix/xxx-xxx-xxx-gnulibc/include

prefix/lib/gcc-lib/xxxx-xxx-xxx-gnulibc/2.8.1/include

2.库文件

cos()等函式库的选项要多加 -lm

编译的时候:

※gcc会去找-L

※再找gcc的环境变量LIBRARY_PATH

※再找内定目录 /lib /usr/lib /usr/local/lib 这是当初compile gcc时写在程序内的

================================================

2

================================================2.利用Linux系统上已有的开发库

(1).查看库文件提供了哪些调用

可以用nm命令自己查看库文件提供了哪些调用

(2).通过头文件查看函数的定义

================================================

3

================================================

3.gcc选项

总体选项 (Overall Option) :(-c(生成目标但不连接) -S(汇编) -E(预处理) -o file(生成指定的文件) -pipe -v(显示过程) -x language (设定文件所使用的语言,使后缀名无效`c', 可用参数`objective-c', `c-header', `c++', `cpp-output', `assembler', and `assembler-with-cpp'))

语言选项 (LANGUAGE OPTIONS) :(-ansi 只支持 ANSI 标准的 C 语法.这一选项将禁止 GNU C 的某些特色)

预处理器选项 (Preprocessor Option) :(-Aassertion -C -dD -dM -dN -Dmacro[=defn] -E -H -idirafter dir -include file -imacros file -iprefix file -iwithprefix dir -M -MD -MM -MMD -nostdinc -P -Umacro 相当于C语言中的#undef macro -undef -DMACRO 以字符串“1”定义 MACRO 宏, -DMACRO=DEFN 以字符串“DEFN”定义 MACRO 宏)

汇编器选项 (ASSEMBLER OPTION) :(-Wa,option )

连接器选项 (LINKER OPTION) :(-llibrary -nostartfiles -nostdlib -static -shared -symbolic -Xlinker option -Wl,option -u symbol )

目录选项 (DIRECTORY OPTION):(-Bprefix -Idir -I- -Ldir)

警告选项 (WARNING OPTION) :(-w 不生成任何警告信息,-Wall 生成所有警告信息)

调试选项 (DEBUGGING OPTION):(-a -dletters -fpretend-float -g -glevel -gcoff -gxcoff -gxcoff+ -gdwarf -gdwarf+ -gstabs -gstabs+ -ggdb -p -pg -save-temps -print-file-name=library -print-libgcc-file-name -print-prog-name=program )

优化选项 (OPTIMIZATION OPTION) :(-O0不进行优化处理,-O或-O1优化生成代码 -O2进一步优化 -O3比-O2更进一步优化,包括inline函数)

目标机选项 (TARGET OPTION) :(-b machine -V version )

机器相关选项 (MACHINE DEPENDENT OPTION):(-m486 针对 486 进行代码优化)

代码生成选项 (CODE GENERATION OPTION) :(-fpic -fPIC)

Linux下编译程序时,经常会遇到“undefined reference to XXX” 报错,

这里总结一些可能的原因和解决方案,给需要的朋友:

说道undefined reference error,先提一下Linux gcc链接规则:

链接的时候查找顺序是:

-L 指定的路径, 从左到右依次查找

由 环境变量 LIBRARY_PATH 指定的路径,使用":"分割从左到右依次查找

/etc/ld.so.conf 指定的路径顺序

/lib 和 /usr/lib (64位下是/lib64和/usr/lib64)

动态库调用的查找顺序:

ld的-rpath参数指定的路径, 这是写死在代码中的

ld脚本指定的路径

LD_LIBRARY_PATH 指定的路径

/etc/ld.so.conf 指定的路径

/lib和/usr/lib(64位下是/lib64和/usr/lib64)

一般情况链接的时候我们采用-L的方式指定查找路径, 调用动态链接库的时候采用LD_LIBRARY_PATH的方式指定链接路径.

另外注意一个问题,就是只要查找到第一个就会返回,后面的不会再查找. 比如-L./A -L./B -lx 在A中有libx.a B中有libx.a和libx.so, 这个时候会使用在./A的libx.a 而不会遵循动态库优先的原则,因为./A是先找到的,并且没有同名动态库存在

对于动态链接库,实际的符号定位是在运行期进行的.在编译.so的时候,如果没有把它需要的库和他一起进行联编,比如libx.so 需要使用uldict, 但是忘记在编译libx.so的时候加上-luldict的话,在编译libx.so的时候不会报错,因为这个时候libx.so被认为是一个库,它里面存在一些不知道具体实现的符号是合法的,是可以在运行期指定或者编译另外的二进制程序的时候指定.

如果是采用 g++ -Lpath -lx 的方式进行编译,链接器会发现所需要的uldict的符号表找不到从而报错,但是如果是程序采用dlopen的方式载入,由于是运行期,这个程序在这个地方就直接运行报错了.另外还有一种情况就是一个对外的接口在动态库中已经声明定义了,但是忘记实现了,这个时候也会产生类似的错误.

如果在运行期报出这样的错误,就要注意是否是由于某些库没有链接进来或者某些接口没有实现的原因产生

有了上述基础,不难看出,undefined reference error错误的原因是:

没有指定对应的库(.o/.a/.so) 使用了库中定义的实体,但没有指定库(-lXXX)或者没有指定库路径(-LYYY),会导致该错误,

连接库参数的顺序不对 在默认情况下,对于-l 使用库的要求是越是基础的库越要写在后面,无论是静态还动态

gcc/ld 版本不匹配 gcc/ld的版本的兼容性问题,由于gcc2 到 gcc3大版本的兼容性存在问题(其实gcc3.2到3.4也一定程度上存在这样的问题) 当在高版本机器上使用低版本的机器就会导致这样的错误, 这个问题比较常见在32位的环境上, 另外就在32位环境不小心使用了64位的库或者反过来64位环境使用了32位的库.

C/C++相互依赖和链接 gcc和g++编译结果的混用需要保证能够extern "C" 两边都可以使用的接口,在我们的64位环境中gcc链接g++的库还需要加上 -lstdc++,具体见前文对于混合编译的说明

运行期报错 这个问题基本上是由于程序使用了dlopen方式载入.so, 但.so没有把所有需要的库都链接上,具体参加上文中对于静态库和动态库混合使用的说明


欢迎分享,转载请注明来源:内存溢出

原文地址:https://54852.com/yw/8322329.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2023-04-15
下一篇2023-04-15

发表评论

登录后才能评论

评论列表(0条)

    保存