关于程序运行时加载动态库失败的解决方法

时间:2022-12-30 16:42:44

一般我们在Linux下执行某些外部程序的时候可能会提示找不到共享库的错误, 比如:

error while loading shared libraries: libevent-1.4.so.2: cannot open shared object file: No such file or directory

原因一般有两个, 一个是操作系统里确实没有包含该共享库(lib*.so.*文件)或者共享库版本不对, 遇到这种情况那就去网上下载并安装上即可.

另外一个原因就是已经安装了该共享库, 但执行需要调用该共享库的程序的时候, 程序按照默认共享库路径找不到该共享库文件.

所以安装共享库后要注意共享库路径设置问题, 如下:

1) 如果共享库文件安装到了/lib或/usr/lib目录下, 那么需执行一下ldconfig命令

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

2) 如果共享库文件安装到了/usr/local/lib(很多开源的共享库都会安装到该目录下)或其它"非/lib或/usr/lib"目录下, 那么在执行ldconfig命令前, 还要把新共享库目录加入到共享库配置文件/etc/ld.so.conf中, 如下:

# cat /etc/ld.so.conf
include ld.so.conf.d/*.conf
# echo "/usr/local/lib" >> /etc/ld.so.conf
# ldconfig

3) 如果共享库文件安装到了其它"非/lib或/usr/lib" 目录下,  但是又不想在/etc/ld.so.conf中加路径(或者是没有权限加路径). 那可以export一个全局变量LD_LIBRARY_PATH, 然后运行程序的时候就会去这个目录中找共享库.

LD_LIBRARY_PATH的意思是告诉loader在哪些目录中可以找到共享库. 可以设置多个搜索目录, 这些目录之间用冒号分隔开. 比如安装了一个MySQL到/usr/local/mysql目录下, 其中有一大堆库文件在/usr/local/mysql/lib下面, 则可以在.bashrc或.bash_profile或shell里加入以下语句即可:

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

一般来讲这只是一种临时的解决方案, 在没有权限或临时需要的时候使用.


如果程序需要的库文件比系统目前存在的库文件版本低,可以做一个链接。比如:

error while loading shared libraries: libncurses.so.4: cannot open shared 
object file: No such file or directory 

ls /usr/lib/libncu* 
/usr/lib/libncurses.a   /usr/lib/libncurses.so.5 
/usr/lib/libncurses.so  /usr/lib/libncurses.so.5.3 

可见虽然没有libncurses.so.4,但有libncurses.so.5,是可以向下兼容的 
建一个链接就好了 
ln -s  /usr/lib/libncurses.so.5.3  /usr/lib/libncurses.so.4



------------------

一.一般安装动态库方式

     #./configure

     #make

    #make install    

    这样,动态库一般安装在/lib、/usr/lib、/usr/local/lib、自定义目录下。

二.找不到共享库文件的原因

   1.压根就没有此共享库,也就是说系统中根本就没有此库或者说没装,这时,从网上下载一些词库装上去即可;

    2.已经安装了该共享库, 但执行需要调用该共享库的程序的时候, 程序按照默认的路径找不到共享库,这也是众多人面对的情形,下面主要针对此原因进行说明。

三.linux寻找动态链接库的顺序

    1.编译代码时指定的动态库搜索路径,这里说明一下,不是Makefile中的-L等指定的目录;

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

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

    4.系统默认搜索路径/lib;

    5.系统默认搜索路径/usr/lib.

四.基于顺序的解决方法

1.编译时指定目录:

     在程序文件中的.dynamic段包含了一个叫DT_RPATH的项,是一个以冒号分隔的库文件搜索目录列表,用以搜索动态库。

     在编译程序时,加入 ”-WI,-rpath =目录“选项,即将动态库文件搜索路径加入到可执行的连接文件中,如一个程序main需要使用libaa.so库,

      则编译如下,gcc -o main -L. -laa -WI,rpath=./ main.c ,即在执行main程序时,main会先在当前目录./下查找所需要的动态库文件。

2.LD_LIBRARY_PATH指定目录:

     LD_LIBRARY_PATH为环境变量,可以export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:动态库目录,可以在运行程序时的终端上键入,

     此时,其只对当前的登录有效,即关闭此终端后失效;在~/.bashrc或.bash_profile中添加一行后并source ~/.bashrc,这样可以永久使用。

3.加入/etc/ld.so.conf文件:

    一般此文件的内容为:include /etc/ld.so.conf.d/*.conf

在其下面添加一行动态库的搜索目录,然后在终端输入ldconfig命令即可。

ldconfig是个什么东东?它是一个linux程序,通常在/sbin下,是root权限的,简单的说,它的作用是将/etc/ld.so.conf列出的路径下的库文件

缓存到/etc/ld.so.cache中以供使用,因此在改动库文件后一定要运行ldconfig.

4和5.将库文件放在这两个系统默认搜索路径下即可。

五.明明安装了高版本,但是还是嫌库版本低

       如经常在论坛上看到有人问"为什么我已经安装了glib-2.4.x,但是编译gtk -2.4.x 还是提示glib版本太低阿?

这就涉及到PKG_CONFIG_PATH环境变量。

一般在编译安装库时,会出现类似如下情形(编译gtk -2.4.13):

checking forpkg-config... /usr/bin/pkg-config
checking for glib-2.0 >= 2.4.0 atk >= 1.0.1 pango >= 1.4.0... Package glib-2.0 was not found in the pkg-config
search path.
Perhaps you should add the directory containing `glib-2.0.pc'to thePKG_CONFIG_PATH environment variable
No package 'glib-2.0' found
configure: error: Library requirements (glib-2.0 >= 2.4.0 atk >= 1.0.1 pango >= 1.4.0) not met; consider adjusting
the PKG_CONFIG_PATH environment variable if your libraries are in a nonstandard prefix so pkg-config can findthem.

那这三个红色表明的是干什么用的呢?

pkg-config用来向configure程序提供系统软件信息,如软件的版本、库的版本、路径等,这些信息都放在*.pc下。

如库装在了/usr/local下,则对应的.pc文件一般在/usr/local/lib/pkgconfig下,要将此目录添加到PKG_CONFIG_PATH中

也就是说,在执行./configure时,pkg-config会查找PKG_CONFIG_PATH指定目录下的.pc文件来提供系统软件的信息。