来自https://gcc.gnu.org/onlinedocs/gcc-8.1.0/gcc/Optimize-Options.html#index-fsemantic-interposition
-fsemantic-interposition
某些对象格式(例如ELF)允许动态链接器插入符号。这意味着对于从DSO导出的符号,编译器无法执行程序间传播,内联和其他优化,因为预期所讨论的功能或变量可能会发生变化。尽管此功能很有用,例如,通过调试实现重写内存分配功能,但在代码质量方面却很昂贵。使用-fno-semantic-interposition,编译器假定如果函数发生插入,则覆盖函数将具有完全相同的语义(和副作用)。同样,如果变量发生插入,则变量的构造函数将相同。该标志对于显式声明为内联的函数(不允许插入以更改语义)不起作用,而对于显式声明为弱的符号无效。
受保护的
受保护的可见性类似于默认可见性,不同的是它表示定义模块中的引用绑定到该模块中的定义。也就是说,声明的实体不能被另一个模块覆盖。
听起来完全一样。
除了-fno-semantic-interposition
明确地将标记为default
的任何功能更改为protected
以外,还有什么实际区别?
答案 0 :(得分:1)
这个问题很难回答,因为当前-fsemantic-interposition
实际上不起作用。在此示例中,
int a;
int
f1 (int a)
{
return a;
}
int
f2 (void)
{
return f1 (a) - a;
}
f2
的主体即使使用return 0;
(也可以使用-O2 -fsemantic-interposition
有效地优化为-O2 -fno-semantic-interposition
,以防文档中的选项含义颠倒) 。 I filed a bug.
可能的目的是-fsemantic-interposition
会禁用此类优化,因此您最终需要调用f1
并对结果进行显式计算。
ELF符号可见性与之实际上并不相关,主要是因为它仅适用于动态链接。链接编辑器仍可以在静态链接时插入符号(例如,使用-z muldefs
选项),因此编译器应该确实提供一种启用插入而无需更改符号属性的方式(因此除__attribute__ ((weak))
以外的其他内容。
答案 1 :(得分:0)
-fno-semantic-interposition
应该与代码生成有关。 -fvisibility=protected
与符号属性有关。 protected
的可见性早于-fsemantic-interposition
,正如Ulrich Drepper的How to Write Shared Libraries所述,这是您不应该使用的可见性属性。
通用ELF ABI定义了另一种可见性模式:受保护。在 该方案对在同一对象中定义的符号的引用是 总是对本地满意。但是符号仍然在外面可用 DSO。这听起来像是通过以下方式优化DSO的理想机制 避免使用导出的符号(请参阅第2.2.7节),但事实并非如此。 处理对受保护符号的引用比 正常查找。问题是ISO C标准的要求。 该标准要求函数指针指向相同的 功能,可以比作平等。该规则将被违反 快速简单的实现受保护的对象 能见度。假设一个应用程序引用了 DSO中的选定功能。在DSO中还有另一个 引用所述功能的功能。指针在 该应用程序指向该功能的PLT条目 在应用程序的PLT中。如果是受保护的符号查找 会简单地返回内部函数的地址 DSO的地址会有所不同。 在没有此要求的编程环境中 在函数指针上使用受保护的可见性 将是有用的和快速的。但是由于通常只有 系统上动态链接程序的一种实现 tem,此实现必须处理C程序 同样,强烈建议不要使用受保护的对象。
如果您希望您的库引用其自身的全局变量而没有插入的可能性(并且由于避免了PLT,可以更快地使用函数),则首选方法是使用隐藏别名定义符号并在内部使用隐藏别名。