GCC:内部可见性“在现实世界的使用中毫无用处”?
Posted
技术标签:
【中文标题】GCC:内部可见性“在现实世界的使用中毫无用处”?【英文标题】:GCC: In what way is visibility internal "pretty useless in real world usage"? 【发布时间】:2014-02-18 02:25:21 【问题描述】:我目前正在使用 GCC 为 QNX (x86) 开发一个库,并且我想制作一些仅在库中使用且对其他模块不可见的符号,尤其是使用该库的代码。
这已经可行,但是,在研究如何实现它时,我在 GCC 的文档中发现了一个非常令人担忧的段落(参见 http://gcc.gnu.org/onlinedocs/gcc-4.8.2/gcc/Code-Gen-Options.html#Code-Gen-Options,flag -fvisibility 的解释):
尽管有命名法,但默认总是意味着公开;即,可用 从共享对象外部链接。受保护和 internal 在实际使用中非常没用,所以唯一的其他 常用选项被隐藏。默认 if -fvisibility 不是 指定是默认值,即,使每个符号公开——这会导致 与以前版本的 GCC 的行为相同。
我对“内部”可见性在实际使用中毫无用处非常感兴趣。根据我从 GCC 文档的另一段(http://gcc.gnu.org/onlinedocs/gcc-4.8.2/gcc/Function-Attributes.html#Function-Attributes,对可见性属性的解释)的理解,可见性“内部”甚至比可见性“隐藏”更强(对我更有用):
内部可见性类似于隐藏可见性,但具有额外的 处理器特定的语义。除非 psABI 另有规定, GCC 定义内部可见性意味着函数永远不会 从另一个模块调用。将此与隐藏函数进行比较, 虽然它们不能被其他模块直接引用,但可以 通过函数指针间接引用。通过表明一个 函数不能从模块外部调用,GCC 可以用于 实例省略 PIC 寄存器的加载,因为已知 调用函数加载了正确的值。
谁能详细解释一下?
【问题讨论】:
【参考方案1】:如果您只想隐藏内部符号,只需使用-fvisibility=hidden
。它完全符合您的要求。
internal
标志比hidden
标志更进一步。它告诉编译器 ABI 兼容性并不重要,因为模块之外的任何人都不会使用该函数。如果某些外部代码确实设法调用了该函数,它可能会崩溃。
不幸的是,有很多方法可以意外地将internal
函数暴露给外界,包括函数指针和 C++ 虚方法。例如,许多库使用回调来发出事件信号。如果您的程序使用这些库之一,则绝不能使用internal
函数作为回调。如果你这样做了,编译器和链接器不会发现任何错误,而且你的程序会出现微妙的、难以调试的崩溃错误。
即使您的程序现在不使用函数指针,它也可能在几年后开始使用它们,那时每个人(包括您)都忘记了这个限制。为了微小的性能提升而牺牲安全性通常是一个坏主意,因此 internal
可见性不是推荐的项目范围默认设置。
internal
可见性在您尝试优化一些频繁使用的代码时会更有用。您可以使用__attribute__ ((visibility ("internal")))
标记这几个特定功能,它告诉编译器速度比兼容性更重要。您还应该为自己留下评论,因此请记住永远不要使用指向这些函数的指针。
【讨论】:
感谢您的精彩解释。我想我误解了我在第一篇文章中引用的文档。我的印象是,可以通过某种方式从其他模块中获取指向隐藏函数的指针,并且在从外部世界隐藏相应函数时,从这个意义上讲,内部函数比隐藏函数更强大。我想我现在明白了。除此之外,调用内部无用有点令人担忧;如果是,为什么要支持?【参考方案2】:我无法提供深入的答案,但我认为“内部”可能不切实际,因为它取决于处理器。您可能会在某些系统上获得预期的行为,但在其他系统上您只会“隐藏”。
【讨论】:
以上是关于GCC:内部可见性“在现实世界的使用中毫无用处”?的主要内容,如果未能解决你的问题,请参考以下文章