I have a fairly large project with multiple interfaces and implementations. The code was implemented on a linux environment using g++ (5.4 I think). After porting the code to Windows and running it with VS15 (MSVC v140) I got an access violation after trying to access a casted pointer.
This is the inheritance hierarchy in the code below:
A
/ \
virtual / \
/ |
B |
| | virtual
C |
| |
\ /
\ /
D
In the real code the inheritance design includes more classes so please don't pick on why this is the way I inherit from A
.
I've narrowed down the code to present only what is necessary.
The following runs with gcc and prints foo called
twice (Live demo on rextester), but with msvc on the second call to foo
crashes with access violation (Live demo on rextester)
#include <iostream>
class A{};
class B : public virtual A{};
class C : public B
{
public:
virtual void foo() = 0;
};
class D : public virtual A, public C
{
public:
bool convert(int id, B** ext)
{
if (id == 1)
{
*ext = (C*)this;
return true;
}
if (id == 42)
{
C** pp_ext = (C**)(ext);
*pp_ext = (C*)this;
return true;
}
return false;
}
void foo() override
{
std::cout << "foo called" << std::endl;
}
};
int main()
{
D s;
C* foo_ext = nullptr;
s.convert(42, (B**)&foo_ext);
foo_ext->foo();
foo_ext = nullptr;
s.convert(1, (B**)&foo_ext);
foo_ext->foo();
return 0;
}
First - Am I missing a fundamental error in the *ext = (C*)this;
conversion?
Second - Why is this code different in the two compilers?
EDIT:
This code uses pointers, pointers to pointers and is built with this inheritance for good reasons (one of which is ABI compliant interface).
dynamic_cast
doesn't change the behavior in this case.If I call
static_cast<C*>(*ext)->foo();
after*ext = (C*)this;
it will call foo, but fail after returning fromconvert
. This is something I have already understood and this is what made me understand that the solution for42
is a (good?) solution.