Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/157.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ Visual Studio 2013在存在/OPT:ICF的情况下是否正确优化?_C++_C++11_Visual Studio 2013_Optimization - Fatal编程技术网

C++ Visual Studio 2013在存在/OPT:ICF的情况下是否正确优化?

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

我希望下面的程序始终返回0。但是,对于Visual Studio 2013(更新4),该程序在发布版本中退出1。我不确定这是否是一个bug,或者编译器的优化器是否正确,是否依赖于某些边缘行为。如果CONST宏已关闭,则release exe返回0。如果优化器确实是正确的,我可以得到为什么允许它发出它所做的代码的原因吗

#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优化将仅适用于相同的通信数据,而这些通信数据的地址未被记录
,这表明它不适用于本案例。评论不适用于扩展讨论;这段对话已经结束。