确切地说,“-fno-semantic-interposition”与“-fvisibility=protected”有何不同?

o11*_*11c 5 c c++ gcc elf

来自https://gcc.gnu.org/onlinedocs/gcc-8.1.0/gcc/Optimize-Options.html#index-fsemantic-interposition

- 语义插入

某些对象格式(例如 ELF)允许动态链接器插入符号。这意味着,对于从 DSO 导出的符号,编译器无法执行过程间传播、内联和其他优化,以应对相关函数或变量可能发生的变化。虽然此功能很有用,例如通过调试实现重写内存分配函数,但在代码质量方面代价高昂。使用 -fno-semantic-interposition ,编译器假设如果函数发生插入,则覆盖函数将具有完全相同的语义(和副作用)。类似地,如果变量发生插入,则变量的构造函数将是相同的。该标志对于显式声明为内联的函数(不允许插入来改变语义)和显式声明为弱的符号没有影响。

来自https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#index-visibility-function-attribute

受保护的

受保护的可见性类似于默认可见性,只不过它指示定义模块中的引用绑定到该模块中的定义。也就是说,声明的实体不能被另一个模块覆盖。

这听起来完全一样。

除了-fno-semantic-interposition更改显式标记default为 的任何函数之外,还有什么真正的区别吗protected

PSk*_*cik 0

-fno-semantic-interposition应该是关于代码生成的。-fvisibility=protected是关于符号属性的。protected可见性出现在前面-fsemantic-interposition,正如 Ulrich Drepper 的《如何编写共享库》中所解释的,它是您不应该使用的可见性属性。

\n\n
\n

通用 ELF ABI 定义了另一种可见性模式:受保护。在此方案中,对同一对象中定义的符号的引用始终在本地得到满足。但这些符号在 DSO 之外仍然可用。这听起来像是一种通过避免使用导出符号来优化 DSO 的理想机制(请参阅第 2.2.7 节),但事实并非如此。\n 处理对受保护符号的引用甚至比正常情况更昂贵抬头。该问题是 ISO C 标准中的一项要求。该标准要求可以比较指向同一函数的函数指针是否相等。如果快速且简单地实现受保护的可见性,就会违反此规则。假设一个应用程序引用了 DSO 中的受保护函数。DSO 中还有另一个引用该函数的函数。应用程序中的指针指向应用程序 xe2x80x99s PLT 中函数的 PLT 条目。如果受保护的符号查找仅返回 DSO 内函数的地址,则地址会有所不同。在没有此要求的编程环境中,对函数指针使用受保护的可见性将很有用,并且快速地。但由于系统上通常只有一种动态链接器实现,并且该实现也必须处理 C 程序,因此强烈建议不要使用 protected。

\n
\n\n

如果您希望库引用自己的全局变量而不可能进行插入(并且由于避免了 PLT,函数的速度更快),首选方法是使用隐藏别名定义符号并在内部使用隐藏别名。

\n