未定义的符号:for -fvisibility = hidden

时间:2012-02-13 16:52:49

标签: xcode linker symbols

我遇到了无法修复的链接器问题(使用MacOS和xcode)。

首先,当我用-fvisibility = hidden编译时,一切都很好。如果我省略那个标志,我会得到

"XYZ::IPlugView::iid", referenced from:
     __ZN9XYZ9IPlugView3iidE$non_lazy_ptr in pluginview.o
     (maybe you meant: __ZN9XYZ9IPlugView3iidE$non_lazy_ptr)

我不知道这是否相关,但在此之前是一些警告,如

  

ld:警告:非虚拟thunk到XYZ ... :: release()在xyz / foo.o中有不同的可见性(隐藏),在xyz / bar.o中有(默认)

任何想法都将不胜感激.... 谢谢!

1 个答案:

答案 0 :(得分:1)

警告实际上可能是相关的。这些警告试图告诉你的是,有一个名为XYZ...::release()的符号,这个符号定义了两次,一次在文件xyz/foo.o中(可能是从xyz/foo.cc编译而来),一个在文件xyz/bar.o(可能是从xyz/bar.cc编译的),但是,符号不是两次定义的,具有相同的可见性,一个符号是默认的(在您正在编译的当前二进制文件库中可见),一个是隐藏的(仅在您正在编译的当前二进制文件库中可见)。当然,同一个符号不能有两种不同的可见性。

使用-fvisibility=hidden告诉编译器:每当没有代码注释定义符号的可见性时,请隐藏此符号。这可能解决了您的问题,因为曾经隐藏的重复符号和默认值现在两次被隐藏,因为以前默认的定义可能是隐式默认的,现在它隐式隐藏,这意味着符号被隐藏了两次这解决了冲突,因为这两个符号可能被链接器视为一个符号。

在源代码中,有两种方法可以通过属性或编译指示来设置符号的可见性。要隐藏符号,您可以在其定义前添加__attribute__ ((visibility ("hidden"))),也可以在源文件中的某处放置一个pragma #pragma GCC visibility push(visibility),使其下面的所有符号定义都隐藏起来,直到您使用pragma #pragma GCC visibility pop返回先前的可见性状态(如果没有前一个,则返回默认状态),使用另一个pragma将可见性更改为其他内容或文件的末尾,无论什么是第一位的。

我认为在您的情况下,有问题的符号曾经在foo.cc中定义,具有明确的可见性(隐藏)和bar.cc中的一次,没有明确的可见性,因此它是默认的或隐藏的,具体取决于您的{ {1}}旗帜。