constexpr 在联合中初始化结构时,msvc visual c++ 静默错误代码生成
Posted
技术标签:
【中文标题】constexpr 在联合中初始化结构时,msvc visual c++ 静默错误代码生成【英文标题】:msvc visual c++ silent incorrect code generation when constexpr initializing struct within union 【发布时间】:2016-12-21 19:53:13 【问题描述】:考虑以下 sn-p 修剪以说明问题:
#include <cstdio>
struct A
union
struct int a0, a1; aa;
int bb[2];
;
#if 1 //bug
constexpr A(int a0, int a1) : aaa0, a1
#else //OK
constexpr A(int a0, int a1) : bba0, a1
#endif
;
int main()
A t02, 3; std::printf("%d %d\n", t0.aa.a0, t0.aa.a1); //2 3 (OK)
static A t12, 3; std::printf("%d %d\n", t1.aa.a0, t1.aa.a1); //2 3 (OK)
constexpr A t22, 3; std::printf("%d %d\n", t2.aa.a0, t2.aa.a1); //2 3 (OK)
static constexpr A t32, 3; std::printf("%d %d\n", t3.aa.a0, t3.aa.a1); //0 0 (??)
msvc 2015 update 3 和 2017 rc1 通过对 t3 进行零初始化而不是使用给定值正确初始化它来静默生成错误代码。 gcc 和 clang 都可以。
我考虑报告一个错误,但它太麻烦了(我不使用 IDE)。如果您关心,请确认这是一个错误,并让微软可能关注的人知道它。
【问题讨论】:
你不需要使用IDE来report a bug。 虽然您可能有理由,但编写这样的代码有什么好的理由吗?对我来说static
和 constexpr
似乎相反。
只是好奇...如果您不关心举报,我为什么要举报?
此错误已报告here。
【参考方案1】:
我可以使用 x86-32 和 x86-64 编译器在 VS 2015 上重现这一点。
我还可以确认当前版本的 GCC、Clang 和 ICC 可以正确编译它。我在语言标准中也找不到任何禁止您所做的事情。无论是在编译时(如您所料)还是在运行时初始化对象,该实现都有一定的余地,但 MSVC 根本不初始化它。
正如所料,当对象的声明被移动到命名空间范围时,也会出现同样的问题,例如:
#include <cstdio>
struct A
union
struct int a0, a1; aa;
int bb[2];
;
constexpr A(int a0, int a1) : aaa0, a1
;
namespace
constexpr A t3 2, 3 ;
;
int main()
std::printf("%d %d\n", t3.aa.a0, t3.aa.a1);
...以及如果对象被声明为空结构的静态成员。
虽然可见效果是零初始化,但这实际上并不是编译器正在做的事情。相反,它根本无法在相应的数据段中发出值,因此当代码在调用printf
时尝试从该地址加载一个值以压入堆栈时,它最终会压入一个零。
这里的union
似乎是重现该错误的关键。如果A
只包含结构aa
,则没有问题。简单地删除bb
以离开一个成员工会也可以解决问题。
请注意,您在submit a bug report to Microsoft for the VS 2017 compiler 处拥有所需的一切(不需要使用 IDE)。问题中包含的代码是一个独立的示例,可以很好地演示该问题。如果您真的不想自己做,请告诉我,我会提交错误。
【讨论】:
感谢您的分析。请提交错误。以上是关于constexpr 在联合中初始化结构时,msvc visual c++ 静默错误代码生成的主要内容,如果未能解决你的问题,请参考以下文章
将函数指针分配给 constexpr 结构中的 typedef 函数的正确 C++ 方法是啥?
与 MSVC 链接错误,但与 constexpr 的 g++ 无关
当值是非常量但使用常量表达式初始化时使用 constexpr?
为啥从 constexpr 引用生成的汇编代码与 constexpr 指针不同?