为什么 Leopard 会用 $non_lazy_ptr 破坏一些符号?更重要的是,修复未定义符号错误的最佳方法是什么,因为符号已被 $non_lazy_ptr 破坏?
5 回答
来自:开发者连接 - 间接寻址
间接寻址是代码生成技术的名称,它允许从另一个文件引用一个文件中定义的符号,而无需引用文件明确了解定义该符号的文件的布局。因此,定义文件可以独立于参考文件进行修改。间接寻址最大限度地减少了必须由动态链接器修改的位置数量,这有助于代码共享并提高性能。
当一个文件使用另一个文件中定义的数据时,它会创建符号引用。符号引用标识从中导入符号的文件和引用的符号。有两种类型的符号引用:非惰性和惰性。
加载模块时,动态链接器会解析非惰性符号引用(绑定到它们的定义)。非惰性符号引用本质上是一个符号指针——一个指针大小的数据。编译器为数据符号或函数地址生成非惰性符号引用。
惰性符号引用在第一次使用时由动态链接器解析(而不是在加载时)。对引用符号的后续调用直接跳转到符号的定义。惰性符号引用由符号指针和符号存根组成,这是一小部分直接取消引用并跳过符号指针的代码。当编译器遇到对另一个文件中定义的函数的调用时,它会生成惰性符号引用。
用人类的话说:编译器生成带有 $non_lazy_ptr 附加到它们的存根以加速链接。您可能会看到从 _Foo$non_lazy_ptr 引用的函数 Foo 未定义,或者类似的东西 - 这些不是一回事。确保在您将应用程序链接到的目标文件/库中实际声明并导出符号。至少那是我的问题,我还认为这是一个奇怪的链接器问题,直到我发现我的问题出在其他地方 - 在 Google 上发现了其他几个可能的原因。
ranlib -c libwhatever.a
是解决该问题的可靠方法。在为 iOS 构建 PJSIP 库时,我遇到了同样的问题。这个库使用了一个基于 autoconf 的 make 系统,但需要对各种文件进行一些调整以使 iOS 一切正常。在此过程中,我设法删除了库规则中的 ranlib 行,然后开始在我的项目链接中收到关于未定义_PJ_NO_MEMORY_EXCEPTION
引用的错误。_PJ_NO_MEMORY_EXCEPTION$non_lazy_ptr
将 ranlib 行添加回库文件解决了它。现在我在 rules.mak 中的 LIBS 完整条目是
$(LIB): $(OBJDIRS) $(OBJS) $($(APP)_EXTRA_DEP)
if test ! -d $(LIBDIR); then $(subst @@,$(subst /,$(HOST_PSEP),$(LIBDIR)),$(HOST_MKDIR)); fi
$(LIBTOOL) -o $(LIB) $(OBJS)
$(RANLIB) -c $(LIB)
希望这有助于其他人尝试将通用 UNIX 配置的外部库与 iPhone 或 iOS 一起使用。
如果其他人遇到了我遇到的同样问题:
头文件里有a extern NSString* const someString;
,但是忘记放实现文件了。作为NSString* const someString=@"someString";
这解决了它。
你的库文件上的ranlib -c 解决了这个问题