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 是啥?