GCC默认导出所有符号与MSVC默认不导出任何东西之间的设计原理是啥?

Posted

技术标签:

【中文标题】GCC默认导出所有符号与MSVC默认不导出任何东西之间的设计原理是啥?【英文标题】:Whats the design rationale between GCC exporting all symbols by default vs MSVC not exporting anything by default?GCC默认导出所有符号与MSVC默认不导出任何东西之间的设计原理是什么? 【发布时间】:2015-03-13 17:58:35 【问题描述】:

C++ 编译器 GCC 和 MSVC 之间的许多主要区别之一是,首先默认导出共享库中的所有符号,而 MSVC 不导出任何符号。

一些含义是,在 MSVC 中,您必须导出显式实例化模板类。

虽然我已经接受了这一点,但我想知道从编译器设计者的角度来看,每种方法的设计含义、权衡取舍等是什么?

【问题讨论】:

GCC 的行为几乎肯定是为了与现有的 UNIX 编译器兼容而选择的。 ELF 规范说符号默认具有全局可见性。这是 C 语言的传统行为:符号是全局的,除非声明为 static 【参考方案1】:

这可能与它们各自操作系统中的可执行文件和库有关。

在 Windows 上,库 (DLL) 和可执行文件是相同的。从字面上看,您可以将 .dll 重命名为 .exe,它将运行保护模式存根并输出一些错误(同样,保护模式,因此它只能在 16 位系统上工作)。鉴于它们是相同的,并且您可以(并且可以!)从实际的可执行文件中导出符号,您会期望默认不导出任何内容吗?

然而,在 Linux 上,可执行文件是它们自己的东西,而代码库(共享对象,.so)是另外一回事。事实上,如果我没记错的话,.so 文件更接近档案(.a,一种 gcc 库——但实际上不是档案)。不需要像在 Windows 中那样包含 .lib 来使用共享库,因为它一种库文件。鉴于您明确地将您的输出编译为这个共享库,我真的没有看到任何奇怪的地方,只是默认导出所有内容。

【讨论】:

A .so 与 .a 完全不同 那么图书馆?这是其中之一,对吗?好久没用 Linux 工具链了。 “库”可以指代.so(动态库或共享库)或.a(静态库或存档),但它们是非常不同的东西。 好的,我添加了一条注释。但它并没有改变帖子的重点,因为您正在编译和链接以创建(共享)库的意图,编译器继续执行并实际导出您正在编译的内容没有任何问题。跨度> 使用 ELF 时,可执行文件和共享对象之间没有重要区别。事实上,许多发行版使用 PIC 可执行文件(标记为 ET_DYN,而不是您期望的 ET_EXEC)作为强化措施。

以上是关于GCC默认导出所有符号与MSVC默认不导出任何东西之间的设计原理是啥?的主要内容,如果未能解决你的问题,请参考以下文章

控制共享库的导出符号时,与“gcc -fvisibility=hidden”等效的 CMake 是啥?

将导出的符号保存在共享库中

so库文件控制导出符号

从 DLL 中去除特定符号

使用 babel 和 webpack 转换代码时,导出默认值不会被转换

MEF:“可组合部件应包含至少一个导出”