为什么这个库dlopen秩序很重要?

时间:2014-09-25 15:25:46

标签: c++ linux dynamic-linking dlopen

我有一个库CandData,以便(相关)$ nm libCandData.so

             U _ZN10CandHandle13SetCandRecordEP10CandRecord
             U _ZN10CandHandle7SetLockEv
000000011610 T _ZNK10CandRecord13GetCandHeaderEv
             U _ZTI10CandHandle

图书馆候选人$ nm libCandidate.so

00000001f018 T _ZN10CandHandle13SetCandRecordEP10CandRecord
00000001f270 T _ZN10CandHandle7SetLockEv
             U _ZNK10CandRecord13GetCandHeaderEv
000000241500 V _ZTI10CandHandle

所以,他们有循环依赖。我可以通过延迟加载Candidate加载这些, 按顺序完成所有工作:

dlopen("libCandidate.so", RTLD_LAZY | RTLD_GLOBAL);
dlopen("libCandData.so",  RTLD_NOW | RTLD_GLOBAL);

但是首先尝试延迟加载CandData:

dlopen("libCandData.so",  RTLD_LAZY | RTLD_GLOBAL);
dlopen("libCandidate.so", RTLD_NOW | RTLD_GLOBAL);

导致dlopen报告:

dlopen Error: libCandData.so: undefined symbol: _ZTI10CandHandle

我不明白为什么这个命令很重要?根据我的理解,V意味着 该符号是弱链接但具有默认定义,因此可以看到可能不需要立即解决。但是这两个库都有U->T依赖。

为什么一个订单有效,而另一个订单无效?

1 个答案:

答案 0 :(得分:2)

  

我不明白为什么这个命令很重要?

顺序很重要,因为虽然未解析的 function 引用可能会被延迟解析,但 data 引用却不能(并且_ZTI10CandHandle不是函数)。

您应该查看重定位(使用nm),而不是查看readelf -Wr输出。您将观察到符号libCandidate.so的{​​{1}}中的重定位类型与符号_ZTI10CandHandle的{​​{1}}中的重定位类型不同。