这个钻石继承UB是MinGW中的一个错误吗?
Posted
技术标签:
【中文标题】这个钻石继承UB是MinGW中的一个错误吗?【英文标题】:Is this diamond inheritance UB a bug in MinGW? 【发布时间】:2013-05-31 22:28:23 【问题描述】:#include <iostream>
#include <sstream>
class VeryBase
protected:
int a_;
public:
VeryBase() : a_(1)
virtual operator std::string()
return "0";
;
class Base1 : public virtual VeryBase
protected:
int b_;
public:
Base1() : b_(2)
operator std::string()
return "1";
;
class Base2 : public virtual VeryBase
protected:
int c_;
public:
Base2() : c_(3)
operator std::string()
return "2";
;
class TargetClass : public Base1, public Base2
protected:
int d_;
public:
TargetClass() : d_(4)
operator std::string()
std::ostringstream s;
s << a_ << ' ' << b_ << ' ' << c_ << ' ' << d_ << std::endl;
return s.str();
;
int main()
VeryBase* a = new TargetClass;
Base1* b = dynamic_cast<Base1*>(a);
Base2* c = dynamic_cast<Base2*>(a);
std::cout << std::string(*a) //1 2 3 4
<< std::string(*b) //1 2 3 4
<< std::string(*c) //? ? ? ?
<< std::endl;
我有这样的代码。它可以在 Windows 8 下的 MSVC 2012 x64、g++ 4.7 和 Clang++ 3.2(x86 和 x64)下在 Ubuntu 12.10 和 13.04 下按预期工作。然而,当使用 MinGW 4.7 x86 或 MinGW 4.8 x64 编译时,带问号的行显示了未定义的行为(对不起,我以为我做到了)。
调试器输出表明此时链接到 TargetClass 的 vtable 存在问题。放置断点表明 TargetClass::operator string() 加载了严重取消引用的对象。但是,使用显式 dynamic_cast 会产生正确的输出。
我想知道什么可能导致这个问题。如果是MinGW的bug,估计一出现就解决了,因为它打破了C++的核心概念之一。
【问题讨论】:
“未定义行为”是语言定义中的一个技术术语。这意味着仅语言定义没有说明会发生什么。如果您在运行代码时看到奇怪的事情发生,它不一定“表现出未定义的行为”。 正式地,代码需要#include <string>
在顶部的某个位置。这可能与问题无关。
【参考方案1】:
这是 mingw gcc 的一个已知问题。
不要使用虚拟继承,问题就会消失。
Bugtracker http://sourceforge.net/p/mingw/bugs/1679/
【讨论】:
【参考方案2】:这看起来像是一个编译器错误(或dynamic_cast
的运行时支持中的错误)。代码看起来是正确的,尽管我没有仔细挖掘它。当然,除非发布的代码不是产生问题的代码。
【讨论】:
【参考方案3】:我刚刚测试过:
32 位和 64 位 MinGW-w64 GCC 4.6/4.7/4.8 版本 MSVC 11.0 和 MSVC 11.0 11 月 CTP 32 位 Clang 3.2 使用 GCC 4.6 libstdc++全部在 Windows 上,并且全部给出输出:
1 2 3 4
1 2 3 4
1 2 3 4
这与 Linux 上的 Clang 和 GCC 相同。
这是否是未定义的行为,我不确定。没用过dynamic_cast
。
【讨论】:
谢谢。我想知道我是否使用 Qt 包破坏了构建。 我想是这个:download.qt-project.org/official_releases/qt/5.0/5.0.1/…以上是关于这个钻石继承UB是MinGW中的一个错误吗?的主要内容,如果未能解决你的问题,请参考以下文章