为什么``````````````')''默认值不是默认值
Why `-fvisibility-inlines-hidden` is not the default?
我要看看我的理解是否正确。
inline
是C 编译器的建议,以便在函数更好的情况下替换一个函数,因此将其称为"从图书馆外部"的程序标记为嵌套的过程不应可靠,并且在逻辑上应该默认隐藏它们,以防止他们称呼它们作为对编译器或代码库的更新可以更改决定(从而删除inline
D功能和ABI断开?(。
似乎不是默认设置,应该设置-fvisibility-inlines-hidden
来实现这一目标。我在这里问为什么是这种情况?是否设置具有任何真实用例
它们在逻辑上应默认隐藏
C 需要所有功能(包括inline
功能(在所有翻译单元中具有相同的地址。也应在所有翻译单元之间共享本地静态。如果将程序作为多个共享对象(.SO文件(构建,则隐藏内联函数违反了这些要求。
内联函数应该具有公共可见性,以便动态链接器可以在运行时从所有现有的定义中选择一个定义。
GCC Wiki提到以下:
-fvisibility-inlines-hidden
可以在没有源更改的情况下使用,,除非您需要覆盖它,以覆盖地址身份对于函数本身很重要的嵌入式或任何功能本地静态数据。。
考虑以下示例。可执行资源:
// main.cpp
#include <cstdio>
struct A { };
inline A &foo()
{
static A a;
return a;
}
int main()
{
void *p = &foo();
std::printf("main() - %pn", p);
}
共享对象来源:
#include <cstdio>
struct A { };
inline A &foo()
{
static A a;
return a;
}
static __attribute__((constructor)) void init()
{
void *p = &foo();
std::printf("main() - %pn", p);
}
如果您同时构建并链接可执行的对象,则可以看到foo
总是在两个翻译单元中返回相同的地址。
现在,如果您将__attribute__((visibility("hidden")))
添加到这些内联函数,那么您将看到该地址在不同的翻译单元中不同。
这不是某些C 程序可能期望的。
当今大多数人认为inline
与实际功能内部无关。这不是完全正确的。精灵目标试图使动态链接透明,例如如果程序作为单个可执行文件或多个共享对象,则应行为相同。
使精灵需要所有具有公众可见性的功能,但要通过got或plt来调用,就好像它是"导入"功能一样。这是必需的,以便每个函数都可以被另一个库(或可执行文件本身(超越。这也禁止为所有公共非内部功能的插条(请参阅第3.5.5节,这表明应通过plt进行公共函数调用(。
代码对公共内联函数的代码恰好是可能的,因为inline
允许在内联函数的多个定义不等的定义时,程序行为是不确定的。
有趣的说明:clang违反了这一精灵的要求,并且能够在小精灵目标上嵌入公共功能。GCC可以使用-fno-semantic-interposition
标志。
inline
是C 编译器的建议
否。最初是这种情况,也许是90年代后期,但很长一段时间都没有。
请参阅此答案,以提供一个很好的解释。
因此,调用从图书馆外部进行的标记的程序不应可靠
- 您的初始假设已经是错误的,因此因此,正在从错误的前提开始
-
即使编译器 do inline呼叫(它可以使用或不使用
inline
关键字(,这是在A 特定呼叫站点上完成的。插入并不是函数发生的事情,必须始终像往常一样发射,而是函数调用。编译器完全有可能将某些呼叫置于函数,而不是其他电话,这取决于其对呼叫网站上最佳代码的看法。
现在,尚不清楚您认为库中的inline
是什么问题,因此很难直接解决该问题。
内联是C 编译器在函数更好的情况下替换函数的建议,因此调用从库外部进行了标记为"从库外部"的过程不应可靠的,因此在逻辑上应该默认隐藏它们
。
编译器仍然可以决定内联一些呼叫,并将其中一些呼叫留下。在这种情况下,您将在所有要链接在一起的库中获得几个夹具函数的副本。
此外,标准在某种程度上要求&foo
在您程序中的任何地方都具有相同的地址,尽管标准没有对DSO/DLL说任何内容,因此编译器在这些方面具有自由度(实际上,MSVC遵循相反的方法默认情况下留下所有东西(。
然而,似乎不是默认设置,应该设置-Fvisibilinsible-Inlines Hidden以实现这一目标。
尽管名称,-fvisibility-inlines-hidden
仅影响内线的类成员函数。对于其他所有内容,-fvisibility=hidden
就足够了。
没有设置具有任何真实用例的设置,并且仅仅是因为遗产原因?
是。IIRC该标志是在GCC 3.2(或足够接近(中实现的;使其默认会破坏很多旧的代码。
- 当给定默认值时,为什么此模板参数推导失败
- 为什么在使用指针时不采用类成员的默认值,而不是直接实例化对象时?
- 为什么 std::move 不将默认移动构造函数中的源变量更改为默认值?
- 为什么无法在可变参数模板中将尾随模板参数指定为默认值?
- 为什么不能使用"( )"为类的非静态数据成员提供默认值?
- 为什么"std::enable_if"需要默认值?
- 为什么``````````````')''默认值不是默认值
- 为什么在指定其所有模板参数具有默认值的模板类时需要<>?
- 如果 Proactor 设计模式优于异步 I/O,为什么它在 ASIO 中不是默认值?
- 为什么C 11将不存在的值定义为默认值
- 为什么 MSVC 和 GCC 不能使用具有默认值的字段初始化结构
- 为什么 C++11 从 std::vector 的填充构造函数的原型中删除了默认值?
- 为什么不能将类构造函数参数设置为默认值?
- 为什么 boost::p rogram_options 在定义默认值时会抛出有关必需参数的错误
- 为什么我的对象中的变量被重置为默认值
- 为什么我的堆栈对象在创建后会更改默认值
- 为什么当窗口在win32上失去焦点时,被覆盖的非客户端区域显示默认值
- 为什么只有一个参数值的函数之后必须为每个参数指定默认值?
- 为什么我总是在传递位置参数时得到默认值
- 为什么c++不允许函数参数作为默认值使用后一个参数