Является ли это наследство алмазов UB ошибкой в ​​MinGW?

#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;
}

У меня есть такой код. Он работает, как и ожидалось, с MSVC 2012 x64 под Windows 8, g ++ 4.7 и Clang ++ 3.2 (x86 и x64) под Ubuntu 12.10 и 13.04. Однако строка с вопросительными знаками демонстрирует неопределенное поведение при компиляции с MinGW 4.7 x86. или MinGW 4.8 x64 (простите, я так и думал)

Вывод отладчика говорит о том, что в этот момент существует проблема со связью с vtable TargetClass. Размещение точек останова показывает, что TargetClass :: operator string () загружен с плохо разыменованным объектом. Однако, если указать явный dynamic_cast, вы получите правильный вывод.

Интересно, что может вызвать эту проблему. Если бы это была ошибка MinGW, она, вероятно, была бы решена, как только появилась, потому что это нарушает одну из основных концепций C ++.

4

Решение

Это известная проблема с mingw gcc.

Не используйте виртуальное наследование, и проблема исчезнет.

Баг трекер http://sourceforge.net/p/mingw/bugs/1679/

4

Другие решения

Это похоже на ошибку компилятора (или ошибку в поддержке времени выполнения для dynamic_cast). Код выглядит правильно, хотя я не тщательно его копал. Если, конечно, опубликованный код не является кодом, который создает проблему.

1

Я только что проверил с:

  • 32-битные и 64-битные сборки MinGW-w64 GCC 4.6 / 4.7 / 4.8
  • MSVC 11.0 и MSVC 11.0 Ноябрь CTP
  • 32-битный Clang 3.2 с использованием GCC 4.6 libstdc ++

все на винде, и все выдают вывод:

1 2 3 4
1 2 3 4
1 2 3 4

это то же самое, что Clang и GCC в Linux.

Является ли это неопределенным поведением или нет, я не уверен. Никогда не использовался dynamic_cast,

1
По вопросам рекламы ammmcru@yandex.ru
Adblock
detector