人类的孤独像是一种与生俱来的残疾。

由“error while loading shared libraries”引起的问题的一些总结

C语言 smallfish 1538℃

先解决这个问题,后面再展开几个相关库的内容。

该错误产生的原因非常明确,即共享库加载失败。一般后续还有更详细的信息“:cannot open shared object file: No such file or directory”,即提示无法打开共享目标文件,找不到此文件或目录。
 
出现此问题的具体可能多种多样,但结果是一样的,没有加载到共享库。因此需要一一排除。首先看看是哪个库出现的问题,然后:
1、该库是否存在/lib,/usr/lib目录下?如果不存在则要看看/etc/ld.so.conf文件中是否有配置此库文件所在目录;如果有配置,且这些目录中没有此库文件,就要把该库文件放入这些目录。
2、有时配置是,而且已配置的目录下也有相应的库文件,但仍出错,这样就有可能是版本不对了,不过这时的提示不会是找不到文件或目录。
3、很多时候我们并不是用到常规的库文件,又或者我们的用户本身没有操作/etc/ld.so.conf以及读写/lib、/usr/lib等目录的权限,甚至我们只希望把库文件放在程序执行目录或者用户有权限存取的目录,因此就需要另一种办法。即在当前的shell环境中添加LD_LIBRARY_PATH变量。例如:export LD_LIBRARY_PATH=./lib:$LD_LIBRARY_PATH,这样就把当前shell目录下的lib目录添加到库加载目录了。
通过以上三种方式,问题应该都可以解决,不然就可能还有其他方面错误。
 
从上述解决问题的思路上其实可以简单窥探到linux系统(其他系统应该也是类似)对共享库加载方式,即在程序执行之初由系统来装载程序所用到的那些库文件。至于装载方式这里不加扩展,有兴趣的可以参考《Linux C一站式编程》(宋劲彬)一书,个人认为这本书写得是真好。不过不同的人在不同的学习阶段去看这本书可能会有不同看法,我是先有几年C工作经验再去看的,看完之后感觉对C的认识又加深很多。回到问题上,系统在加载共享库时会有它的一套机制,我们这里要说的是系统搜索共享库路径的顺序,默认是从/lib、/usr/lib这些系统目录进行搜索,当然还是通过/etc/ld.so.conf文件来设置,具体的可以在网上找找。个人认为知道这些原理就好。在碰到类似问题时知道从哪些方向去解决就行了,我们这里还是以解决问题为主。如果有兴趣和精力去探索具细就更好了。
 
说到共享库一定会想到静态库。
 
静态库是一些目标文件的集合,我们在编译连接程序时候就会用到,当程序编译完成之后就不需要了。举例来说:我们写了一个常用的工具函数tools(),在项目A和项目B都有用到,这样我们就不需要在两个项目中都写一份tools()函数的源码,而仅需要在编译时加上对这个库的链接(当然,需要加上头文件引用,具体使用方法这里不展开讲),这样就可以在项目A和项目B的目标代码中都有tools()函数了,因此在运行项目的时候也不再需要这个静态库了。
而与静态库不同的是,使用到动态库的项目在编译时也同样要链接动态库,但是动态库中的目标代码并不会被连接到项目的目标文件中去,它仅仅是提供一些链接规则,告诉程序在执行时,如何去找到这些目标代码。同样假设项目A和B都有用到libc.so动态库中的tools()函数。在项目A执行时,系统首先从项目A的目标代码中发现执行项目A需要libc.so,因此系统就会按既定的搜索规则去查找这个库文件,如果找不到就会报出本文标题所示的错误,如果找到了则加载进内存,当项目A用到库中的tools函数时,就跳转到libc.so中的tools()函数所示的代码块执行相应代码。如果此时项目B又执行了,系统发现项目B所需的libc.so已经被加载了,此时它将不再加载libc.so库,而是直接使用已加载的库。当然,前面说的“直接跳转到libc.so中的tools函数代码执行”这一表述可能并不准确,有些时候可能会拷贝一个副本,而并不是在相应代码块直接执行。这里仅是为了简单说明执行方式,有兴趣的同学可以继续深究这个问题。
 
大致了解了动态库的加载与使用方式之后我们肯定会想:可不可以在程序运行时,由编写程序指定在什么节点分支,根据不同情况来决定要不要加载动态库呢?答案当然是可以的。这就是后面要说的动态加载库。其实库本身没区别,区别只在于使用方式上。前面说的动态库在编译链接的时候指定,然后在程序运行时由系统负责加载。动态加载则由程序本身使用dlopen()、dlsym()等函数来打开加载动态库,获取函数指针以及其他操作。

转载请注明:OpenMind » 由“error while loading shared libraries”引起的问题的一些总结

喜欢 (0)