考虑这两个功能:
void foo() {}
void bar() {}
Run Code Online (Sandbox Code Playgroud)
是保证&foo != &bar
吗?
同样的,
template<class T> void foo() { }
Run Code Online (Sandbox Code Playgroud)
是保证&foo<int> != &foo<double>
吗?
我知道折叠函数定义有两个连接器.
MSVC积极地COMDAT折叠函数,因此具有相同实现的两个函数可以转换为一个函数.作为副作用,这两个函数共享相同的地址.我的印象是这是非法的,但我无法找到标准中的哪些内容是非法的.
Gold链接器还可以折叠功能,包括a safe
和all
设置. safe
意味着如果采用了一个功能地址,它就不会折叠,all
即使采用了地址也会折叠.因此safe
,如果函数具有不同的地址,则黄金的折叠表现为.
虽然折叠可能是意料之外的,并且存在依赖于具有不同地址的不同(相同实现)函数的代码(因此折叠可能是危险的),在当前的C++标准下它实际上是非法的吗?(此时为C++ 14)(自然如果safe
折叠是合法的)
c++ function-pointers one-definition-rule language-lawyer comdat-folding
我花了很长时间才发现我的代码中有一个错误被触发/OPT:ICF
:
因为/ OPT:ICF可以将相同的地址分配给不同的函数或只读数据成员(使用/ Gy编译的const变量),它可以破坏依赖于函数或只读数据成员的唯一地址的程序.
(我一直在存储和比较函数指针的相等性,当链接器丢弃相同的函数时会断开这些指针.)
现在我需要找到我可能做过这样事情的每一个地方.
测试用例当然是微不足道的:
//MSVC: /Gy /link /OPT:ICF
int test1(void) { return 0; }
int test2(void) { return 0; }
int main(void) { return test1 == test2; }
Run Code Online (Sandbox Code Playgroud)
我试过-Wall
,-Wextra
,-Weverything
,-pedantic
,等,但他们没有产生警告.
是否有任何编译器选项或工具(无论是Visual C++,GCC,Clang还是其他部分)可以分析我的代码并告诉我在哪里比较函数指针,就像在上面的代码中一样?
这个问题在 SO 上有一些答案,但我的略有不同。在标记为重复之前,请试一试。
MSVC 一直提供 /Gy编译器选项,以允许将相同的函数折叠到 COMDAT 部分中。同时,链接器还提供了 /OPT:ICF 选项。我的理解是这两个选项必须结合使用吗?也就是说,前者将函数封装到 COMDAT 中,后者消除了冗余的 COMDAT。那是对的吗?
如果是,那么我们要么同时使用要么都关闭?