在ubuntu下代码编译通过的情况下,经常出现运行时加载动态库出错的情况。这些问题很琐碎,不具备任何技术含量,纯属耽误时间,这也是linux系统的通病,花里胡哨,故弄玄虚。
为了减少初学者在这种无意义的事情上浪费大量的时间,本文对这个问题提供一点解决方案,这些方案都是在Ubuntu18.04上测试过的,希望对需要者有所帮助。
这里使用的是最小化的代码,主程序是mytest,其运行时需要调用libtest.so, 成功调用后输出信息:Hello Shared Library!
否则会抱怨找不到动态库。
本文的工作目录为/home/eric/dlltest
![471f47b8ef9e76a93e0f9ae7a7633318.png](https://i-blog.csdnimg.cn/blog_migrate/5aa95ef18056a00bdf359042b30b98f8.png)
error while loading shared libraries:libtest.so: cannot open shared object file: No such file or directory
这就对了,符合本文的预期,libtest.so已经被移除了,所以会报错。
下面将libtest.so拷贝回来。
有:
![a2c052d6e8cb5db89873c6e960237cb6.png](https://i-blog.csdnimg.cn/blog_migrate/383c391e8b8f21062299fa5157c18eac.png)
可见这样mytest就找到了动态库libtest.so。
![bf42090b91707f7c0e2a809ebada582d.png](https://i-blog.csdnimg.cn/blog_migrate/4c224add1baa67c61bedd3ee17b61726.png)
再次将libtest.so移动到/home/eric/lib/下面,有:
![5c24f3b31d5bc19b97f57d2a86daff74.png](https://i-blog.csdnimg.cn/blog_migrate/b599d94f201ad7355d624e6386de2f3c.png)
这时候,
![958fb89862bbb5046df0396c389c960a.png](https://i-blog.csdnimg.cn/blog_migrate/1918a081ab5a0ca228af331ddcbc0536.png)
dlltest下面只有mytest执行文件,继续测试有:
![f7cf6997304f7f35b323fe974a1d6877.png](https://i-blog.csdnimg.cn/blog_migrate/974f0bab07d2dd530406b2284ffc1af5.png)
错误继续出现,这样就对了。下面想办法能够让mytest程序能够找到动态库libtest.so。
第一种方法:
使用
![5fb6a6af9576be241cc5a0756d9d2292.png](https://i-blog.csdnimg.cn/blog_migrate/c87c7da18225203b2b95da93501ade4e.png)
可以看到,动态库找到了,然而这种方法关闭了窗口之后就没效果了。
![935136db1996b81075bed102baa370a8.png](https://i-blog.csdnimg.cn/blog_migrate/47ff0bf2b0feb168e44a48bb5ff68a63.png)
重启命令窗口后问题继续出现,
这时候需要
第二种方法,修改.bashrc文件
进入到/home/eric下(eric是本文在ubuntu上的用户名)
![7f44915d454dbc3ce000c185006127c5.png](https://i-blog.csdnimg.cn/blog_migrate/d52d0f0ec2deb8b6e64ca7b007cc4173.png)
![afbd0805f12ca3ccffc6e73c0b038716.png](https://i-blog.csdnimg.cn/blog_migrate/8020533e24ab3f5729c25b171f576e2d.jpeg)
在.bashrc文件末尾加入:
export LD_LIBRARY_PATH=/home/eric/lib:$LD_LIBRARY_PATH
![f3fb4eb5ea55bd92c5b1ffe918cf64d7.png](https://i-blog.csdnimg.cn/blog_migrate/b41755034feed675c9b0fd2bf95a6e78.png)
也就是上图第121行,保存退出后,运行source .bashrc
![f7d24618050eccfa267a25b39487da7b.png](https://i-blog.csdnimg.cn/blog_migrate/6c172970597251afd05bdb38fcc0efeb.png)
可见/home/eric/lib 已经在库路径里面了。
这是进入到/home/eric/dlltest目录:
![c0f20884400ea5673d61a5da87e7414c.png](https://i-blog.csdnimg.cn/blog_migrate/f4734ff8e439c0e532085d465da9c553.png)
可见,这次动态库路径是对的,为了保险起见,关闭窗口,重新打开,有:
![9a443bc0708fdb4535c6bf20c6aa14a7.png](https://i-blog.csdnimg.cn/blog_migrate/5cad69c06731cab5a15e4cd494ccf045.png)
可见还是可以找到的。
下面将export LD_LIBRARY_PATH=/home/eric/lib:$LD_LIBRARY_PATH 从/home/eric/.bashrc文件中注释掉。
![06f7a9e5fa0959e093b451dece63ae3e.png](https://i-blog.csdnimg.cn/blog_migrate/4c46ade5ba4bdec70236e19fe1317c9f.png)
![e9bfa61ad5b1bb914fcf78e598ce9ba4.png](https://i-blog.csdnimg.cn/blog_migrate/707375b641e587dfd659b78f1521775f.png)
可见还是找的到动态库,这不科学!
![937e1931b897d2d4b9f9d7a6e33aff5b.png](https://i-blog.csdnimg.cn/blog_migrate/ef0932f987ac83d00e6a0842eeffbb01.png)
查看库路径果然/home/eric/lib还在,这时候需要运行下source .bashrc,可以看到库变量改变了。
![85e401a2f19abf244ccbfefafa040582.png](https://i-blog.csdnimg.cn/blog_migrate/3e267e167c43155d0ab470b0d5378eaf.png)
不过虽然是库变量改变了,但是还是系统找得到动态库libtest.so,只好关闭窗口重启了:
![59ae123132284d7d80c66274b6abf5ba.png](https://i-blog.csdnimg.cn/blog_migrate/70a378b93a5c796d06ca473b3bac5a0a.png)
这次是真的找不到了。
linux系统下就是经常发生这种非常微妙的小插曲,当你以为搞定了,实际上却是错误的结论,好在本文用了一个最小出错模型,有大量的时间可以耗下去,如果在生产环境,这种代价是承受不起的。
这样第二种方法也测试成功了。下面介绍第三种方法。
第三种方法,修改/etc/ld.so.conf文件
本文的/etc/ld.so.conf内容为:
![41b38597669d28b1d4cc544fac0f6244.png](https://i-blog.csdnimg.cn/blog_migrate/af73ed17ecf6fea7ff8062788f7a6e8a.png)
加上路径/home/eric/lib/
有:
![f452f2b16db2d83cb74ba4be7f819c40.png](https://i-blog.csdnimg.cn/blog_migrate/92bbd48a07b259c4abaf9de35b6d8515.png)
修改后保存。
![46a70391f94c8f55dcba9ebf4da6b6bf.png](https://i-blog.csdnimg.cn/blog_migrate/f684faf90faae84b76ed639e0751cd8b.png)
继续测试mytest,可见还是找不到库。
这是需要运行sudo ldconfig:
![373960104e51b0cafd5542252ec71b47.png](https://i-blog.csdnimg.cn/blog_migrate/e3cbc94f1d5455c67cc1bf242aed2849.png)
本文运行的当前目录是/home/eric/dlltest
可见sudo ldconfig命令不挑当前目录。
为了保险起见,关闭窗口,重新启动:
![b7abe4d9ed8970f683ca2b827c7044ee.png](https://i-blog.csdnimg.cn/blog_migrate/a66a5d8b79d35ec505a72861c27e39cb.png)
可见还是可以找得到的,说明此方法可行。
继续修改etc/ld.so.conf文件,删除路径/home/eric/lib/,并运行sudo ldconfig等有:
![1dbe5a8d043eed5d28a52dd41ab3c9bd.png](https://i-blog.csdnimg.cn/blog_migrate/91729892b6bcbd8bbd1018603c36798f.png)
说明又找不到了,好的,符合预期,重启窗口试一下,虽然不大有可能出现反常,但是怕了,必须验证!
![fa46a9eb20d3e9419bea8f5aff6129b6.png](https://i-blog.csdnimg.cn/blog_migrate/90305ef0e74c4f1d540c217a1eb58da5.png)
还是没找到,说明的确第三种方法是起作用的。
下面介绍第四种方法:
第四种:在/etc/ld.so.conf.d/目录下添加youtest.conf文件
![86e361babeafb1d3a5fffacb758ea30f.png](https://i-blog.csdnimg.cn/blog_migrate/42cc7c91bb258635d3005c841a4607b8.png)
![bfb6958eaff6456f2e0fcc38190bf769.png](https://i-blog.csdnimg.cn/blog_migrate/2cde0e4795b31fa3898fec10b544c7c7.png)
文件内容为/home/eric/lib/
也就是动态库libtest.so的所在路径。
![0cdf131de10bc3fa926e4af7a7ab09d7.png](https://i-blog.csdnimg.cn/blog_migrate/ee7115914aefe3640aa61bf5517f8d01.png)
可以看到youtest.conf文件产生了。
这是运行mytest测试一下:
![a07a105e314c315aa267f5e6fc7a4045.png](https://i-blog.csdnimg.cn/blog_migrate/a6796e9836e18015a73ece824d8456a6.png)
没找到,这符合预期,还没有使用sudo ldconfig命令
![2854441830547271c9445f05445b1569.png](https://i-blog.csdnimg.cn/blog_migrate/50827af6f0bb047b47d569d7b3381141.png)
可见,这次文件youtest.conf起作用了,文件名youtest.conf是为了避嫌,也就是这个可以和mytest不一样,当然后缀名是需要.conf就行。
再次重启窗口,
![074af2b196d7f34c7144dcaaeb9d65bd.png](https://i-blog.csdnimg.cn/blog_migrate/7f51cd63fbf076184aafb190c2525062.png)
可见还是可以找得到动态库。
说明这种方法也是成功的。
综上所述,本文介绍了找动态库的四种方法,也许方法可能会有千千万万种,但是本文不感兴趣,有了这几种方法后,初学者容易有获得感和幸福感,从而有进一步学习的勇气和道路自信,其它的方法都可以触类旁通,进而获得更大意义上的自由。
应该说,本文的环境是WSL下的ubuntu18.04,在其它系统上可能会产生一些细微的差异,需要灵活运用。
后面有时间的话还会有些类似的文章,扫清这种没有任何技术含量的学习障碍,从而使初学者能够将有限的时间放到有价值的事情上去。