海湾合作委员会:内部可视性以什么方式在实际使用中毫无用处"?

时间:2014-01-27 09:51:16

标签: gcc export visibility symbols

我目前正在使用GCC为QNX(x86)开发一个库,我想制作一些在库中专用的符号,对其他模块是不可见的,特别是对使用该库的代码。

这已经有效,但是,在研究如何实现它时,我在GCC的文档中找到了一个非常令人担忧的段落(参见http://gcc.gnu.org/onlinedocs/gcc-4.8.2/gcc/Code-Gen-Options.html#Code-Gen-Options,对flag -fvisibility的解释):

  

尽管有命名法,但默认总是意味着公开;即,可用   从共享对象外部链接。受保护的   内部在实际使用中是相当无用的,所以唯一的另一个   常用选项是隐藏的。缺省的if -fvisibility不是   指定是默认值,即将每个符号设为公共 - 这会导致   与之前版本的GCC相同。

我对“内部”在实际使用中的可见性非常感兴趣。根据我从GCC的文档(http://gcc.gnu.org/onlinedocs/gcc-4.8.2/gcc/Function-Attributes.html#Function-Attributes,可见性属性的解释)的另一段落中所理解的,可见性“内部”甚至比“隐藏”的可见性更强(对我来说更有用):

  

内部可见性就像隐藏的可见性,但附加   处理器特定的语义。除非psABI另有规定,   GCC定义内部可见性意味着函数永远不会   从另一个模块调用。将此与隐藏功能相比较,   虽然它们不能被其他模块直接引用,但可以   通过函数指针间接引用。通过指示a   函数不能从模块外部调用,GCC可能用于   实例省略了PIC寄存器的加载,因为已知它   调用函数加载了正确的值。

有人可以深入解释吗?

2 个答案:

答案 0 :(得分:10)

如果您只想隐藏内部符号,请使用-fvisibility=hidden。它完全符合您的要求。

internal标志远远超过hidden标志。它告诉编译器ABI兼容性并不重要,因为模块外的任何人都不会使用该函数。如果某些外部代码确实设法调用该函数,它可能会崩溃。

不幸的是,有很多方法可以意外地将internal函数暴露给外界,包括函数指针和C ++虚方法。例如,许多库使用回调来发送事件信号。如果您的程序使用其中一个库,则绝不能使用internal函数作为回调。如果这样做,编译器和链接器将不会发现任何错误,并且您的程序将具有细微的,难以调试的崩溃错误。

即使您的程序现在不使用函数指针,当所有人(包括您)都忘记了此限制时,它可能会在未来几年内开始使用它们。牺牲安全性以获得微小的性能提升通常是一个坏主意,因此internal可见性不是建议的项目范围默认值。

如果您尝试优化一些使用频繁的代码,internal可见性会更有用。您可以使用__attribute__ ((visibility ("internal")))标记这些少数特定函数,它告诉编译器速度比兼容性更重要。你也应该为自己留言,所以你要记得永远不要指向这些函数。

答案 1 :(得分:1)

我无法提供深入的答案,但我认为“内部”可能不实用,因为它取决于处理器。您可能会在某些系统上获得预期的行为,但在其他系统上,您只能“隐藏”。