C++ Visual Studio 2013在存在/OPT:ICF的情况下是否正确优化?
我希望下面的程序始终返回0。但是,对于Visual Studio 2013(更新4),该程序在发布版本中退出1。我不确定这是否是一个bug,或者编译器的优化器是否正确,是否依赖于某些边缘行为。如果CONST宏已关闭,则release exe返回0。如果优化器确实是正确的,我可以得到为什么允许它发出它所做的代码的原因吗C++ Visual Studio 2013在存在/OPT:ICF的情况下是否正确优化?,c++,c++11,visual-studio-2013,optimization,C++,C++11,Visual Studio 2013,Optimization,我希望下面的程序始终返回0。但是,对于Visual Studio 2013(更新4),该程序在发布版本中退出1。我不确定这是否是一个bug,或者编译器的优化器是否正确,是否依赖于某些边缘行为。如果CONST宏已关闭,则release exe返回0。如果优化器确实是正确的,我可以得到为什么允许它发出它所做的代码的原因吗 #if 1 # define CONST const #else # define CONST #endif class TypeId { public: bo
#if 1
# define CONST const
#else
# define CONST
#endif
class TypeId {
public:
bool operator== (TypeId const & other) const
{
return id == other.id;
}
private:
TypeId (void const * id)
: id(id)
{}
public:
template <typename T>
static TypeId Get ()
{
static char CONST uniqueMemLoc = 0;
return TypeId(&uniqueMemLoc);
}
private:
void const * id;
};
int main(int, char **)
{
typedef int A;
typedef unsigned int B;
if (TypeId::Get<A>() == TypeId::Get<B>()) {
return 1;
}
return 0;
}
#如果1
#定义常数
#否则
#定义常数
#恩迪夫
类类型ID{
公众:
布尔运算符==(类型ID常量和其他)常量
{
返回id==other.id;
}
私人:
类型id(无效常量*id)
:id(id)
{}
公众:
模板
静态TypeId Get()
{
静态字符常量uniqueMemLoc=0;
返回类型ID(&uniqueMemLoc);
}
私人:
无效常数*id;
};
int main(int,char**)
{
类型定义INTA;
typedef无符号整数B;
if(TypeId::Get()==TypeId::Get()){
返回1;
}
返回0;
}
<>代码>不,此优化不符合C++标准。uniqueMemLoc
的声明为模板的每个实例定义了一个唯一的对象,每个对象都有自己的地址
(如果您使用了字符串文字,情况就不同了。在这种情况下,优化是有效的。)根据草案C++11标准部分14.8
[temp.fct.spec]的说法,这似乎不是一个有效的优化(重点放在后面):
从模板实例化的每个函数模板专门化都具有
它自己的任何静态变量副本。[示例:
template<class T> void f(T* p) {
static T s;
};
void g(int a, char* b) {
f(&a); // calls f<int>(int*)
f(&b); // calls f<char*>(char**)
}
模板空f(T*p){
静态T-s;
};
空g(整数a,字符*b){
f(&a);//调用f(int*)
f(&b);//调用f(char**)
}
这里f(int*)有一个int和
f(char**)有一个char*-类型的静态变量s-结束示例]
因为您获取变量的地址会影响可观察的行为,这将违反
T.C.指出,/opt:noicf
可防止不合规行为
Matt McNabb指出,报告包含以下注释:
因为/OPT:ICF可以导致将相同的地址分配给
不同的函数或只读数据成员(常量变量
使用/Gy编译),它可以破坏依赖于唯一性的程序
函数或只读数据成员的地址。更多
信息,请参阅/Gy(启用功能级别链接)
这表明这可能是故意的不合规行为。Ben Voigt说,这确实意味着优化可能是不一致的,但这一点是有争议的
用户usr发送到一个,它说:
请注意,ICF优化将仅适用于相同的
COMDAT的地址未被记录,并且是只读的。如果
数据不是地址,然后通过ICF破坏地址唯一性
不会导致任何可观察到的差异,因此它是有效的
符合标准
后来的评论说:
即使它完全依靠自己,当
与/Gy结合可能导致潜在的破坏行为
据我所知,为了使/Gy
影响常量变量,必须使用declspec(selectany),但文档中可能会更清楚
至少我们可以看到,/Gw
不应该引入不一致的行为,但是/Gy
与/Gw
结合使用可能会产生不一致的行为。我认为优化器是不正确的。可能与MSVC中的COMDAT折叠有关。是的,/opt:noicf
修复了它。@ShafikYaghmour似乎暗示这是有意的:“由于/OPT:ICF会导致将同一地址分配给不同的函数或只读数据成员(使用/Gy编译的常量变量),因此它会破坏依赖于函数或只读数据成员的唯一地址的程序。有关更多信息,请参见/Gy(启用功能级别链接)。“@usr等一下,我刚刚完全阅读了这篇文章,它说,请注意,ICF优化将仅适用于相同的通信数据,而这些通信数据的地址未被记录
,这表明它不适用于本案例。评论不适用于扩展讨论;这段对话已经结束。