用于 COMDAT 折叠的 MSVC 编译器和链接器选项之间的关系

For*_*ing 5 compiler-construction linker visual-c++ comdat-folding

这个问题在 SO 上有一些答案,但我的略有不同。在标记为重复之前,请试一试。

MSVC 一直提供 /Gy编译器选项,以允许将相同的函数折叠到 COMDAT 部分中。同时,链接器还提供了 /OPT:ICF 选项。我的理解是这两个选项必须结合使用吗?也就是说,前者将函数封装到 COMDAT 中,后者消除了冗余的 COMDAT。那是对的吗?

如果是,那么我们要么同时使用要么都关闭?

For*_*ing 4

来自与我线下交流的人的回答。帮助我更好地理解这些选项。

=====================================

这基本上是正确的。假设我们只谈论 C 或 C++,但没有成员函数。如果没有 /Gy,编译器将创建在某种意义上不可简化的目标文件。如果链接器只需要对象中的一个函数,它就会获取所有函数。这是在库编程中特别要考虑的一个因素,因此,如果您想善待库的用户,您应该将库编写为许多小对象文件,通常每个对象一个非静态函数,以便库的用户库不会因为必须携带实际上从未执行的代码而膨胀。

使用 /Gy,编译器创建具有 COMDAT 的目标文件。每个函数都在其自己的 COMDAT 中,从某种程度上来说,COMDAT 是一个迷你对象。如果链接器只需要对象中的一个函数,它可以只选择该函数。链接器的 /OPT 开关使您可以对链接器通过此选择性执行的操作进行一些控制 - 但如果没有 /Gy,则无法选择任何内容。

或者很少。例如,至少可以想象,链接器可以折叠函数,这些函数都是目标文件中的整个代码,并且碰巧具有相同的代码。当然可以想象,链接器可以消除不包含任何引用的整个目标文件。毕竟,它是通过库中的目标文件来完成此操作的。然而,实践中的规则过去是,如果将非 COMDAT 目标文件添加到链接器的命令行,那么您就是说您希望将其包含在二进制文件中,即使未引用也是如此。可想象的和已完成的之间的差异通常是巨大的。

那么,最好坚持快速回答。链接器选项受益于能够将函数(和变量)与每个目标文件内部分开,但这种分离取决于已组织到 COMDAT 中的代码和数据,这是编译器的工作。

=====================================