为什么`-fvisibility-inlines-hidden`不是默认值? [英] Why `-fvisibility-inlines-hidden` is not the default?

查看:136
本文介绍了为什么`-fvisibility-inlines-hidden`不是默认值?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我要看看我的理解是否正确.

I am asking to see whether my understandings are correct.

inline 是C ++编译器的建议,建议在看起来更好时就替换一个函数,因此从库外部调用标记为内联的过程应该是不可靠的,并且从逻辑上讲,它们应该被隐藏默认情况下,阻止其他人调用它们作为对编译器或代码库的更新可以更改决定(从而删除 inline d函数和ABI损坏?).

inline is a suggestion to C++ compiler for substituting a function whenever it sees better, therefore calling a procedure flagged as inlined from outside of a library shouldn't be reliable and they logically should be hidden by default, preventing others to call them as an update to a compiler or codebase can be change the decision (thus removal of the inlined function and ABI breakage?).

但是,这似乎不是默认设置,应该设置 -fvisibility-inlines-hidden 来实现这一目标.我在这里问为什么会这样?设置不具有任何实际用例,仅因为遗留原因而存在吗?

However it seems that is not the default setting and -fvisibility-inlines-hidden should be set to make that happen. I am asking here why that is the case? Does not setting that has any real use case and it is there just because legacy reasons?

推荐答案

默认情况下,它们在逻辑上应该是隐藏的

they logically should be hidden by default

C ++要求所有函数(包括 inline 函数)在所有翻译单元中都具有相同的地址.本地静态信息也应在所有翻译单元之间共享.如果程序是作为多个共享库(.so文件)构建的,则隐藏内联函数会违反这些要求.

C++ requires all functions (including inline functions) to have the same address in all translation units. Local statics should also be shared among all translation units. Making inline functions hidden violates those requirements if program is built as multiple shared objects (.so files).

内联函数应该具有公共可见性,以便动态链接程序可以在运行时从所有现有定义中选择一个定义.

Inline functions should have public visibility so that dynamic linker could choose one definition from all existing ones at runtime.

GCC Wiki 提到了这一点:

GCC wiki mentions this:

-fvisibility-inlines-hidden 可以不带任何源更改地使用,除非您需要对其内联重写,否则对于地址标识对于函数本身或任何函数本地静态都很重要的内联数据.

-fvisibility-inlines-hidden can be used with no source alterations, unless you need to override it for inlines where address identity is important either for the function itself or any function local static data.


请考虑以下示例.可执行源:


Consider following example. Executable source:

// main.cpp
#include <cstdio>

struct A { };

inline A &foo()
{
    static A a;
    return a;
}

int main()
{
    void *p = &foo();
    std::printf("main() - %p\n", p);
}

共享对象源:

#include <cstdio>

struct A { };

inline A &foo()
{
    static A a;
    return a;
}

static __attribute__((constructor)) void init()
{
    void *p = &foo();
    std::printf("main() - %p\n", p);
}

如果同时构建这两个对象并针对此共享库链接可执行文件,则可以看到 foo 始终在两个翻译单元中返回相同的地址.

If you build both and link executable against this shared object, you can see that foo always returns the same address in both translation units.

现在,如果在这些内联函数中添加 __ attribute __((visibility("hidden"))),那么您会发现该地址在不同的翻译单元中是不同的.

Now if you add __attribute__((visibility("hidden"))) to those inline functions, then you will see that address is different in different translation units.

这不是某些C ++程序可能期望的.

This is not what some C++ program might expect.

当今大多数人认为 inline 与实际的函数内联无关.这是不完全正确的.ELF目标尝试使动态链接透明化,例如如果程序是作为单个可执行文件或多个共享对象构建的,则程序应具有相同的行为.

Most people today think that inline has nothing to do with actual function inlining. This is not exactly true. ELF targets try to make dynamic linking transparent e.g. program should behave identically if it is build as a single executable or as multiple shared objects.

要使其成为可能,ELF要求通过GOT或通过PLT调用具有公共可见性的所有功能,就好像它是导入"功能一样.这是必需的,以便每个函数都可以被另一个库(或可执行文件本身)覆盖.这也禁止内联所有公共非内联函数(请参见第3.5.5节此处,它表明应该通过PLT进行PIC中的公共功能调用.

To make it possible ELF requires all functions with public visibility to be called though GOT or through PLT as if it is "imported" function. This is required so that every function could be overriden by another library (or executable itself). This also forbids inlining for all public non-inline functions (see section 3.5.5 here which shows that public function call in PIC should be made through PLT).

完全可以进行公共内联函数的代码内联,因为当内联函数的多个定义不相等时, inline 允许未定义程序行为.

Code inlining for public inline functions is possible exactly because inline allows program behavior to be undefined when multiple definitions of inline function are not equivalent.

有趣的说明:Clang违反了ELF要求,并且无论如何都可以内联ELF目标上的公共功能.GCC可以使用 -fno-semantic-interposition 标志执行相同的操作.

Interesting note: Clang violates this ELF requirement and is able to inline public functions on ELF targets anyway. GCC can do the same with -fno-semantic-interposition flag.

这篇关于为什么`-fvisibility-inlines-hidden`不是默认值?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆