COMDAT 折叠的 MSVC 编译器和链接器选项之间的关系
Relation between MSVC Compiler & linker option for COMDAT folding
这个问题有一些关于 SO 的答案,但我的答案略有不同。在标记为重复之前,请试一试。
MSVC 始终提供 /Gy compiler 选项,使相同的函数能够折叠到 COMDAT 部分中。同时linker也提供了/OPT:ICF选项。我的理解是否正确,这两个选项必须结合使用?也就是说,前者将函数封装到COMDAT中,而后者消除了冗余的COMDAT。对吗?
如果是,那么我们是同时使用还是同时关闭?
的回答
As explained in the documentation for /Gy, function-level linking
allows functions to be discardable during the "unused function" pass,
if you ask for it via /OPT:REF. It does not alter the actual classical
model for linking. The flag name is misleading. It's not "perform
function-level linking". It merely enables it by telling the linker
where functions begin and end. And it's not so much function-level
linking as it is function-level unlinking. -Raymond
(这个片段可能更有意义 context:here 是关于经典链接模型的帖子:1, 2
简而言之 - 是的。如果只激活一个开关而不激活另一个开关,则不会产生明显的影响。
离线与我交流的人的回答。帮助我更好地理解这些选项。
===================================
这基本上是正确的。假设我们只讨论 C 或 C++,但没有成员函数。如果没有 /Gy,编译器会创建在某种意义上不可简化的目标文件。如果链接器只需要对象中的一个函数,它会获取所有函数。这是库编程中的一个特别考虑,如果你想善待库的用户,你应该把你的库写成很多小的目标文件,通常每个对象一个非静态函数,这样用户库不会因为必须携带实际上从不执行的代码而膨胀。
使用 /Gy,编译器创建具有 COMDAT 的目标文件。每个函数都在它自己的 COMDAT 中,它在某种程度上是一个迷你对象。如果链接器只需要对象中的一个函数,它可以只挑出那个函数。链接器的 /OPT 开关使您可以控制链接器对此 selectivity 执行的操作 - 但如果没有 /Gy,select.
就没有任何意义
或者很少。至少可以想象,链接器可以,例如,折叠目标文件中所有代码的函数,并且恰好具有相同的代码。可以肯定的是,链接器可以删除一个不包含任何引用的目标文件。毕竟,它是通过库中的对象文件来实现的。然而,实践中的规则曾经是,如果您将非 COMDAT 目标文件添加到链接器的命令行,那么即使未被引用,您也表示您希望在二进制文件中包含该文件。可以想象的和已经完成的之间的差异通常是巨大的。
那么,最好坚持快速回答。链接器选项受益于能够从每个目标文件中分离函数(和变量),但分离取决于代码和数据被组织成 COMDAT,这是编译器的工作。
===================================
这个问题有一些关于 SO 的答案,但我的答案略有不同。在标记为重复之前,请试一试。
MSVC 始终提供 /Gy compiler 选项,使相同的函数能够折叠到 COMDAT 部分中。同时linker也提供了/OPT:ICF选项。我的理解是否正确,这两个选项必须结合使用?也就是说,前者将函数封装到COMDAT中,而后者消除了冗余的COMDAT。对吗?
如果是,那么我们是同时使用还是同时关闭?
As explained in the documentation for /Gy, function-level linking allows functions to be discardable during the "unused function" pass, if you ask for it via /OPT:REF. It does not alter the actual classical model for linking. The flag name is misleading. It's not "perform function-level linking". It merely enables it by telling the linker where functions begin and end. And it's not so much function-level linking as it is function-level unlinking. -Raymond
(这个片段可能更有意义 context:here 是关于经典链接模型的帖子:1, 2
简而言之 - 是的。如果只激活一个开关而不激活另一个开关,则不会产生明显的影响。
离线与我交流的人的回答。帮助我更好地理解这些选项。
===================================
这基本上是正确的。假设我们只讨论 C 或 C++,但没有成员函数。如果没有 /Gy,编译器会创建在某种意义上不可简化的目标文件。如果链接器只需要对象中的一个函数,它会获取所有函数。这是库编程中的一个特别考虑,如果你想善待库的用户,你应该把你的库写成很多小的目标文件,通常每个对象一个非静态函数,这样用户库不会因为必须携带实际上从不执行的代码而膨胀。
使用 /Gy,编译器创建具有 COMDAT 的目标文件。每个函数都在它自己的 COMDAT 中,它在某种程度上是一个迷你对象。如果链接器只需要对象中的一个函数,它可以只挑出那个函数。链接器的 /OPT 开关使您可以控制链接器对此 selectivity 执行的操作 - 但如果没有 /Gy,select.
就没有任何意义或者很少。至少可以想象,链接器可以,例如,折叠目标文件中所有代码的函数,并且恰好具有相同的代码。可以肯定的是,链接器可以删除一个不包含任何引用的目标文件。毕竟,它是通过库中的对象文件来实现的。然而,实践中的规则曾经是,如果您将非 COMDAT 目标文件添加到链接器的命令行,那么即使未被引用,您也表示您希望在二进制文件中包含该文件。可以想象的和已经完成的之间的差异通常是巨大的。
那么,最好坚持快速回答。链接器选项受益于能够从每个目标文件中分离函数(和变量),但分离取决于代码和数据被组织成 COMDAT,这是编译器的工作。
===================================