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

I have a code like this. It works as expected with MSVC 2012 x64 under Windows 8, g++ 4.7 and Clang++ 3.2 (both x86 and x64) under Ubuntu 12.10 and 13.04. However, line with question marks demonstrates undefined behavior when compiled with MinGW 4.7 x86 or MinGW 4.8 x64 (sorry, I thought I did).

Debugger output says that there is a problem with linking to vtable of TargetClass at that point. Placing breakpoints shows that TargetClass::operator string() is loaded with badly dereferenced object. Putting explicit dynamic_cast, however, makes right output.

I wonder what can possibly cause this problem. If it was a bug of MinGW, it would probably be solved as soon as it appeared, because it breaks one of the core concepts of C++.

isCasted
  • 41
  • 3
  • 5
    "Undefined behavior" is a technical term in the language definition. It means **only** that the language definition does not say what happens. If you see weird things happening when you run your code it does not necessarily "demonstrate undefined behavior". – Pete Becker May 31 '13 at 22:59
  • 1
    Formally, the code needs `#include ` somewhere at the top. This is probably not related to the problem. – Pete Becker May 31 '13 at 23:01

3 Answers3

4

This is a known issue with mingw gcc.

Do not use virtual inheritance and the issue goes away.

Bugtracker http://sourceforge.net/p/mingw/bugs/1679/

1

This looks like a compiler bug (or a bug in the runtime support for dynamic_cast). The code looks correct, although I haven't dug through it carefully. Unless, of course, the posted code is not the code that produces the problem.

Pete Becker
  • 74,985
  • 8
  • 76
  • 165
1

I have just tested with:

  • 32-bit and 64-bit MinGW-w64 GCC 4.6/4.7/4.8 builds
  • MSVC 11.0 and MSVC 11.0 November CTP
  • 32-bit Clang 3.2 using GCC 4.6 libstdc++

all on Windows, and all giving the output:

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

which is the same as Clang and GCC on Linux.

Whether this is undefined behavior or not, I'm not sure. Never used dynamic_cast.

rubenvb
  • 74,642
  • 33
  • 187
  • 332
  • Thanks for that. I wonder if I've got broken build with Qt package. – isCasted Jun 02 '13 at 18:02
  • I think it's this one: http://download.qt-project.org/official_releases/qt/5.0/5.0.1/qt-windows-opensource-5.0.1-mingw47_32-x86-offline.exe – isCasted Jun 02 '13 at 18:50