在使用redis写C代码的时候遇到的问题,安装redis时 make install可以看到:

mkdir -p/usr/local/include/hiredis /usr/local/lib
cp -a hiredis.h async.h read.h sds.h adapters/usr/local/include/hiredis
cp -a libhiredis.so/usr/local/lib/libhiredis.so.0.13
cd /usr/local/lib &&ln -sflibhiredis.so.0.13 libhiredis.so
cp -a libhiredis.a/usr/local/lib

把redis的头文件放进了/usr/local/include/hiredis,把动态库libhiredis.so和静态库libhiredis.a都放进了/usr/local/lib

于是我就在我的Makefile里面写:

gcc main.c -I/usr/local/include-L/usr/local/lib -lhiredis -o main

OK,gcc通过生成可执行文件main,但是一运行main报错:

error while loading shared libraries:

libhiredis.so.0.13: cannot open sharedobject file: No such file or directory

于是产生了两个疑问:

1. usr/local/lib 里面libhiredis.so和静态库libhiredis.a都有,为什么用的是.so而不是.a?gcc编译链接时写法都是-L库所在路径 -l库名,是否有写法可以区分指明要链接动态库还是静态库?

2. 我在Makefile里面不是已经指明so的位置,并且相应位置确实有libhiredis.so.0.13,为什么运行的时候还是找不到?

针对第一个问题,查了资料之后发现:

ld在链接的时候如果路径下相同库名的静态库和动态库都有,那么会优先使用动态链接库,动态链接库不存在才会使用静态链接库;

如果指明要使用静态链接库,那么需要在编译命令中加入-static参数;

gcc main.c -I/usr/local/include-L/usr/local/lib -lhiredis -static -o main

后来又做了测试发现,-static是一个全局参数,并不是只对一个链接生效,对所有的链接都生效。也就是一旦写上之后所有库都只会去找静态库,就不能指定某些库链静态库,而其它库链动态库;

针对第二个问题其实是很显然的,"link time"(链接时)和"runtime"(运行时),两个基本概念要弄清楚,不能混在一起。-L选项属于链接时,编译出来的可执行文件不知道-L选项后面的值,当然找不到对应的so。而-rpath,LD_LIBRARY_PATH都属于运行时

查资料之后发现运行的时候查找动态库路径顺序如下:

1. 可执行文件中自带的编译时写入的RPATH、RUNPATH

2. LD_LIBRARY_PATH 指定的地方
3. ldconfig 指定的地方:根据/etc/ld.so.cache查找
4. /lib
5. /usr/lib

所以相对应的解决办法有:

1.      使用rpath把so的路径指明并记录到二进制文件中

gcc main.c -I/usr/local/include -L/usr/local/lib -lhiredis –o main -Wl,--rpath=/usr/local/lib

重新编译再运行发现无报错了

关于RPATH、RUNPATH的详细相关作用方法见http://gotowqj.iteye.com/blog/1926771

2.      把libredis.so所在路径加入到LD_LIBRARY_PATH环境变量中

export LD_LIBRARY_PATH= /usr/local/lib:$LD_LIBRARY_PATH

3.      使用ldconfig修改/etc/ld.so.cache

ldconfig命令的用途主要是在默认搜寻目录/lib和/usr/lib以及动态库配置文件/etc/ld.so.conf内所列的目录下,搜索出可共享的动态链接库(格式如lib*.so*),进而创建出动态装入程序(ld.so)所需的连接和缓存文件(一般默认为/etc/ld.so.cache),此文件保存已排好序的动态链接库名字列表

ldconfig通常在系统启动时运行,而当用户安装了一个新的动态链接库时,就需要手工运行这个命令。

由于我们是新安装了redis的动态链接库,因此需要手动把它加到缓存文件中去,具体做法为:

/etc/ld.so.conf下面加一行/usr/local/lib /usr/local/mysql/lib(需要root权限),保存过后ldconfig一下(需要root权限)

4.      把新安装的so拷到/lib或/usr/lib下

衍生问题:那么程序在链接so的时候ld到底做了些什么?(有待后续研究)

ld链接动态库静态库问题相关推荐

  1. CMake 添加头文件目录,链接动态、静态库(添加子文件夹)

    CMake支持大写.小写.混合大小写的命令. 当编译一个需要第三方库的项目时,需要知道: 去哪找头文件(.h),-I(GCC) INCLUDE_DIRECTORIES() 去哪找库文件(.so/.dl ...

  2. cmake中添加引用动态链接_CMake 添加头文件目录,链接动态、静态库(添加子文件夹)...

    CMake支持大写.小写.混合大小写的命令. 当编译一个需要第三方库的项目时,需要知道: 去哪找头文件(.h),-I(GCC) INCLUDE_DIRECTORIES() 去哪找库文件(.so/.dl ...

  3. c语言makecode头文件,cmake 添加头文件目录,链接动态、静态库

    罗列一下cmake常用的命令. CMake支持大写.小写.混合大小写的命令. 1. 添加头文件目录INCLUDE_DIRECTORIES 语法: include_directories([AFTER| ...

  4. cmake 添加头文件目录,链接动态、静态库

    罗列一下cmake常用的命令. CMake支持大写.小写.混合大小写的命令. 1. 添加头文件目录INCLUDE_DIRECTORIES 语法: include_directories([AFTER| ...

  5. VS2015编译32位Opencv310(动态库+静态库,文末有下载链接)

    VS2015编译32位Opencv310(动态库+静态库 编译过得,可以直接用的: http://download.csdn.net/download/longzaihuaxia/9802510 之前 ...

  6. linux库引入之动态库静态库(生成和使用)

    库: 库是一种可执行代码的二进制形式,可以被操作系统载入内存执行.就是将源代码转化为二进制格式的源代码,相当于进行了加密,别人可以使用库,但是看不到库中的内容. 如何使用 用户需要同时具有头文件和库. ...

  7. 硬核拆解动态库静态库

    [Github pages] 动态库与静态库是编程中十分常见的玩意儿,但是如此常见的东西在我真正用心去了解梳理过一遍之后才发现原来这里面有这么多的门道.本文就介绍一波 Linux 平台下,特指 GCC ...

  8. linux系统应用学习(三)--- 动态库静态库

    动态库静态库 库文件:一般指第三方提供的可调用的库函数文件,库文件封存的是函数体,即.c文件里面的内容. 动态库      静态库 Windows下:        xx.dll            ...

  9. linux库--静态库、动态库

    文章目录 一.分文件编程思想 二.动态库静态库 1.概念介绍 2.静态库的制作和使用 3.动态库的制作和使用 一.分文件编程思想 好处: 分模块的编程思想 例如: 网络 a 超声波b 电机c a.功能 ...

  10. linux gcc 包含头文件 动态库 静态库 链接路径问题

    C/C++程序在linux下被编译和连接时,GCC/G++会查找系统默认的include和link的路径,以及自己在编译命令中指定的路径.自己指定的路径就不说了,这里说明一下系统自动搜索的路径. [1 ...

最新文章

  1. mysql 5.7 1054_MySQL5.7更改密码时出现ERROR 1054 (42S22)的解决方法
  2. NLP/CV模型跨界,视觉Transformer赶超CNN?
  3. 【转】QT 串口QSerialPort + 解决接收数据不完整问题
  4. Google Apps – Framework, Phonesky, GmsCore w/ AOSP Build.
  5. Mvc示例代码调试之一----调试工具及设置(用firebug与vs联合调试)
  6. 【遥感物候】C#遥感数据GIMMS 3G NDVI头文件批量生成器(几何校正)
  7. 实操教程|用不需要手工标注分割的训练数据来进行图像分割
  8. 后端薪资要比前端高吗?什么技术是公司的核心技术?前端技术算不算核心技术?
  9. AsyncTask的基本使用
  10. namedpipe资料 政治课报告3000字 base64编码 《近世代数引论》冯克勤 P 1-5 - 学习记录 2020/6/5
  11. navicat 执行sql文件
  12. thinkphp如何调试,打印错误信息sql等
  13. ArcGIS Administartor localhost是无效主机名
  14. 远距离WiFi无线传输方案,CV5200模组通信应用,无线自组网技术
  15. vue.js中文官网下载vue.js失败了?
  16. 网络协议分析(3):FTP
  17. 信息技术重返MBA课程
  18. 运维之查看服务器cpu、内存、硬盘
  19. 计算机放音乐声音小在吗调,电脑放歌声音小怎么办
  20. 今年大火的元宇宙,到底是什么?

热门文章

  1. 【爬虫】使用Scrapy框架进行爬虫详解及示例
  2. b和kb的换算_KB换算
  3. 掘金8000亿早教市场,启蒙APP们还面临哪些难题?
  4. 列举几个:MAC OS科研软件推荐
  5. java 数学库_数学库
  6. conda Collecting package metadata (repodata.json)卡住或 failed问题
  7. Ubalun电动牙刷拆卸及内部刨析
  8. 【哈希链表】 146 LRU、LFU缓存机制
  9. c#计算圆或者圆柱面积体积代码
  10. (最小割求最小割集)poweroj2883病毒侵染