了解 C++ 可见性支持

Posted

技术标签:

【中文标题】了解 C++ 可见性支持【英文标题】:Understanding C++ visibility support 【发布时间】:2021-12-21 17:25:24 【问题描述】:

-- 如GCC Wiki - Visibility 所述。我已经练习了How to use the attribute((visibility("default")))? 和Simple C++ Symbol Visibility Demo,但仍然不明白GCC Wiki - Visibility 文章的某些部分。

在它的Step-by-step_guide 你可以找到

For every non-templated non-static function definition in your library (both headers and source files), decide if it is publicly used or internally used

在其他示例中,我发现只装饰头文件中的声明就足够了。为什么还要修饰源文件中的定义?

If it is publicly used, mark with FOX_API like this: extern FOX_API PublicFunc()

我没有在其他示例中看到这个 extern 关键字,我也从未将它用于公共功能。为什么我必须在这里使用它?

The given macro 以

开头
#ifdef FOX_DLL // defined if FOX is compiled as a DLL

如果使用 CMakeFOX_DLL 在哪里或如何定义?

【问题讨论】:

关于FOX_DLL的问题是Cmake相关的,建议移到专门问题。 【参考方案1】:

在其他示例中,我发现只装饰头文件中的声明就足够了。为什么还要修饰源文件中的定义?

如果全局函数在头文件中声明并且该头文件包含在函数被定义的源文件中,则头文件中的注释就足够了(编译器确实会从头文件中获取属性)。否则,您需要在源代码中对其进行注释。

我没有在其他示例中看到这个 extern 关键字,我也从未将它用于公共功能。为什么我必须在这里使用它?

extern 关键字在函数声明中是可选的,但通常用于清楚起见。

【讨论】:

"标头中的注释就足够了......否则你需要在源代码中对其进行注释。" - 我如何在另一个源文件中调用全局函数而不头文件?对我来说,GCC Wiki - Visibility 中的注释没有多大意义(除了包含源文件)。 @Ingo "我如何在没有头文件的情况下在另一个源文件中调用全局函数" - 通过在源文件中手动声明 extern void foo()。请注意,标头就是这样,一堆extern 声明,它们由预处理器插入到源文件中。 啊.. 是的,当然。没想到这个。【参考方案2】:

您可能会对两种相反的可见性方法感到困惑。您同时命名GCC(来自 UNIX 角)和 DLL(来自 Windows 角)。

UNIX 默认情况下具有完全可见性,Windows 默认情况下不可见。因此,要修改这两个默认值,您必须朝相反的方向移动。

C++(和之前的 C)没有共享库或可见性的概念,这是有道理的:没有太多需要标准化的东西。你最终会得到这样的非便携式方法。

【讨论】:

"要修改这两个默认值,你必须向相反的方向移动" - 只是想指出Linux上的推荐方法是使用-fvisibility=hidden隐藏默认情况下所有符号,然后通过__attribute__((visibility("default"))) 选择性地导出公共符号。这使它与 Windows 相同。

以上是关于了解 C++ 可见性支持的主要内容,如果未能解决你的问题,请参考以下文章

C++ 并发中的内存可见性(无数据竞争)

在 C++ 中声明可见性/访问的方式有何不同?

c++ 特殊方法可见性

具有隐藏可见性的 C++ 模板参数问题

非原子时,C++ 成员更新关键部分内的可见性

C++:警告:“...”声明的可见性高于其字段“...::<anonymous>”的类型