我有一个库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
依赖。
为什么一个订单有效,而另一个订单无效?
答案 0 :(得分:2)
我不明白为什么这个命令很重要?
顺序很重要,因为虽然未解析的 function 引用可能会被延迟解析,但 data 引用却不能(并且_ZTI10CandHandle
不是函数)。
您应该查看重定位(使用nm
),而不是查看readelf -Wr
输出。您将观察到符号libCandidate.so
的{{1}}中的重定位类型与符号_ZTI10CandHandle
的{{1}}中的重定位类型不同。