ere*_*eOn 25 c++ linux g++ shared-libraries dynamic-linking
考虑我们有以下情况:
program动态依赖的程序libfoo.solibfoo.so这取决于什么(好吧,这取决于libstdc++和东西,但我想我们可以省略)program 运行得很好.
突然,libfoo代码发生了变化,一些函数现在在内部使用func_bar()了另一个库提供的函数libbar.so.
libfoo.so重新编译,现在取决于libbar.so.program保持不变,仍然只取决于libfoo.so.
现在当我执行program它时抱怨他找不到func_bar().
这是我的问题:
libfoo.so接口没有改变,只有它的实现.为什么program必须明确地链接libbar.so?libfoo.so依赖libbar.so,libbar.so将自动添加到依赖列表中program,而无需重新编译.但是,ldd program表明情况并非如此.每当库的依赖性发生变化时,必须重新编译(重新链接)依赖于某个库的每个二进制文件,这似乎很奇怪.我有什么解决方案可以防止这种情况发生?
caf*_*caf 17
当你还没有链接的问题出现libfoo.so反对libbar.在编译可执行文件时,默认情况下链接器不允许您保留未定义的引用.但是,当您编译共享库时,它将会 - 并且期望它们在链接时得到满足.这样libfoo可以使用program自己导出的函数- 当您尝试运行它时,动态链接器期望func_bar()由它提供program.问题如下所示:
(foo.c是自包含的)
export LD_RUN_PATH=`pwd`
gcc -Wall -shared foo.c -o libfoo.so
gcc -Wall -L. p.c -lfoo -o p
Run Code Online (Sandbox Code Playgroud)
此时./p,如您所料,正确运行.然后我们创建libbar.so并修改foo.c以使用它:
gcc -Wall -shared bar.c -o libbar.so
gcc -Wall -shared foo.c -o libfoo.so
Run Code Online (Sandbox Code Playgroud)
此时,./p给出您描述的错误.如果我们检查ldd libfoo.so中,我们发现,它并没有对依赖libbar.so-这是错误.要纠正错误,我们必须libfoo.so正确链接:
gcc -Wall -L. -lbar -shared foo.c -o libfoo.so
Run Code Online (Sandbox Code Playgroud)
此时,./p再次正确运行,并ldd libfoo.so显示依赖关系libbar.so.
在Fedora上,动态链接由ld-linux.so.2执行.动态链接器使用/etc/ld.so.cache和/etc/ld.so.preload来查找库文件.
运行ldconfig告诉系统libfoo应该在哪里查找libbar.
ldconfig查找/ lib,/ usr/lib以及/etc/ld.so.conf中列出的任何目录.您可以检查程序使用ldd的库.
有关每个命令的手册页,请参见更多详细信息.
以下是使用共享库的应用程序示例.
Program.cc
#include "foo.h"
#include <iostream>
int main(int argc, char *argv[])
{
for (int i = 0; i < argc; ++i) {
std::cout << func_foo(argv[i]) << std::endl;
}
}
Run Code Online (Sandbox Code Playgroud)
foo.h中
#ifndef FOO_H
#define FOO_H
#include <string>
std::string func_foo(std::string const &);
#endif
Run Code Online (Sandbox Code Playgroud)
foo.cc
#include "foo.h"
std::string func_foo(std::string const &arg)
{
return arg + "|" + __func__;
}
Run Code Online (Sandbox Code Playgroud)
bar.h
#ifndef BAR_H
#define BAR_H
#include <string>
std::string func_bar();
#endif
Run Code Online (Sandbox Code Playgroud)
bar.cc
#include "bar.h"
std::string func_bar()
{
return __func__;
}
Run Code Online (Sandbox Code Playgroud)
使用libfoo.so构建为共享库.
g ++ -Wall -Wextra -fPIC -shared foo.cc -o libfoo.so
g ++ -lfoo -L./-Wall -Wextra program.cc foo.h -o program
ldd program
...
libfoo.so => not found
更新/etc/ld.so.cache
sudo ldconfig/home/tobias/projects/stubs/so/
ldd显示动态链接器找到libfoo.so
ldd program
...
libfoo.so => /home/tobias/projects/stubs/so/libfoo.so(0x00007f0bb9f15000)
在libfoo.so中添加对libbar.so的调用
new foo.cc
#include "foo.h"
#include "bar.h"
std::string func_foo(std::string const &arg)
{
return arg + "|" + __func__ + "|" + func_bar();
}
Run Code Online (Sandbox Code Playgroud)
构建libbar.so并重建libfoo.so
g ++ -Wall -Wextra -fPIC -shared bar.cc -o libbar.so
g ++ -Wall -Wextra -fPIC -shared libbar.so foo.cc -o libfoo.so
ldd libfoo.so
...
libbar.so =>找不到
ldd program
...
libfoo.so => /home/tobias/projects/stubs/so/libfoo.so(0x00007f49236c7000)libbar.so
=> not found
这表明动态链接器仍然找到libfoo.so而不是libbar.so
再次更新/etc/ld.so.cache并重新检查.
sudo ldconfig/home/tobias/projects/stubs/so/
ldd libfoo.so
...
libbar.so => /home/tobias/projects/stubs/so/libbar.so(0x00007f935e0bd000)
ldd program
...
libfoo.so => /home/tobias/projects/stubs/so/libfoo.so(0x00007f2be4f11000)libbar.so
=> /home/tobias/projects/stubs/so/libbar.so(0x00007f2be4d0e000)
找到了libfoo.so和libbar.so.
请注意,最后一步对应用程序没有影响.如果你真的严格运行ldconfig是一种重新连接.奇怪与否链接器需要知道它链接的库的依赖关系.还有很多其他方法可以实现这一点,但这是选择的.
| 归档时间: |
|
| 查看次数: |
5165 次 |
| 最近记录: |