A quick analysis of the assembly code generated by the MSVC ++ 2013 compiler shows that the delegated call from B::B(int) to B() failed. This is a compiler error.
MSVC ++ constructors have a hidden logical parameter that tells the designer whether it is the construction of the derived object itself ( true ) or the built-in base subobject ( false ). In this example, only A::A() should receive true in this hidden parameter, while all calls to the lower-level constructor should receive false . However, when B() is called from B::B(int) , the compiler unconditionally passes 1 ( true ) as a hidden parameter. This is not true.
; Code for `B::B(int)` ... 00F05223 push 1 ; <- this is the problem 00F05225 mov ecx,dword ptr [this] 00F05228 call B::B (0F010F0h) ; <- call to `B::B()` ...
In correctly generated code, when the compiler makes a delegated call to the constructor, it must pass by the value of the parameter received from the caller, and not hard-coded 1 .
The order of direct subconstructor calls made from A::A() in this example is as follows: 1) a common virtual base D , 2) base B , 3) base D1 .
In accordance with the rules of the language, in this case, constructor B and constructor D1 do not have to create their own virtual database D Base D already built at this point by the most derived object A This is exactly what is controlled by this hidden logical parameter. However, when B::B() is called from B::B(int) , the compiler passes an invalid parameter value (this is hardcoded 1 ), which is why B::B() incorrectly assumed that it was building the most derived object. This rotation makes B rebuild the shared virtual base D This override cancels the results of the correct construction already done by A::A() . This later crashes.
AnT
source share