wrong objects addresses using virtual and diamond inheritance

Phil Thompson phil at riverbankcomputing.com
Wed Dec 22 13:12:48 GMT 2021


This should be fixed in the next snapshot.

Thanks,
Phil

On 15/12/2021 10:35, Denis Rivière wrote:
> Hi,
> 
> I experience a new virtual class address issue using sip 
> 4.19.21-4.19.25.
> I have a rather complex C++ inheritance tree, using virtual inheritance 
> and
> diamond inheritance, looking like this:
> 
>     A     B
>     \\   //
>      \\ //
>  D     C
>   \  // \\
>    \//   \\
>     E     F
>     \\   //
>      \\ //
>        G
> 
> (double lines mean virtual inheritance)
> 
> In recent Sip bindings the addresses of the different parts of a G 
> object
> appear to be wrong, thus objects are unusable and cause crashes.
> 
> Here is a simple C++ implementation code:
> 
> // header declarations:
> 
> #include <iostream> // not used here but simplifies the sip MethodCodes
> later
> 
> class A
> {
> public:
>   A();
>   virtual ~A();
>   int a;
> };
> 
> 
> class B
> {
> public:
>   B();
>   virtual ~B();
>   int b;
> };
> 
> class C : public virtual A, public virtual B
> {
> public:
>   C(): c(3) {}
>   virtual ~C() {}
> 
>   int c;
> };
> 
> class D
> {
> public:
>   D();
>   virtual ~D();
>   int d;
> };
> 
> class E: public D, public virtual C
> {
> public:
>   E();
>   virtual ~E();
> };
> 
> class F : public virtual C
> {
> public:
>   F();
>   virtual ~F();
> };
> 
> class G : public virtual E, public virtual F
> {
> public:
>   G();
>   virtual ~G();
>   int g;
> };
> 
> 
> // C++ implementation
> 
> A::A(): a( 1 ) {}
> A::~A() {}
> 
> B::B(): b( 2 ) {}
> B::~B() {}
> 
> C::C() : A(), B(), c( 3 ) {}
> C::~C() {}
> 
> D::D() : d( 4 ){}
> D::~D() {}
> 
> E::E() : D(), C() {}
> E::~E() {}
> 
> F::F() : C() {}
> F::~F() {}
> 
> G::G() : E(), F(), g( 7 ) {}
> G::~G() {}
> 
> 
> // SIP bindings file
> 
> 
> class A
> {
> %TypeHeaderCode
> #include "test.h"
> %End
> 
> public:
>   A();
>   virtual ~A();
>   void __a__();
> %MethodCode
>   std::cout << "A: " << sipCpp << std::endl;
> %End
> 
>   int a;
> };
> 
> 
> class B
> {
> %TypeHeaderCode
> #include "test.h"
> %End
> 
> public:
>   B();
>   virtual ~B();
>   void __b__();
> %MethodCode
>   std::cout << "B: " << sipCpp << std::endl;
> %End
> 
>   int b;
> };
> 
> 
> class C : A, B
> {
> %TypeHeaderCode
> #include "test.h"
> %End
> 
> public:
>   C();
>   virtual ~C();
>   void __c__();
> %MethodCode
>   std::cout << "C: " << sipCpp << std::endl;
> %End
> 
>   int c;
> };
> 
> 
> class D
> {
> %TypeHeaderCode
> #include "test.h"
> %End
> 
> public:
>   D();
>   virtual ~D();
>   void __d__();
> %MethodCode
>   std::cout << "D: " << sipCpp << std::endl;
> %End
>   int d;
> };
> 
> class E : D, C
> {
> %TypeHeaderCode
> #include "test.h"
> %End
> 
> public:
>   E();
>   virtual ~E();
>   void __e__();
> %MethodCode
>   std::cout << "E: " << sipCpp << std::endl;
> %End
> };
> 
> 
> class F : C
> {
> %TypeHeaderCode
> #include "test.h"
> %End
> 
> public:
>   F();
>   virtual ~F();
>   void __f__();
> %MethodCode
>   std::cout << "F: " << sipCpp << std::endl;
> %End
> };
> 
> 
> class G : E, F
> {
> %TypeHeaderCode
> #include "test.h"
> %End
> 
> public:
>   G();
>   virtual ~G();
>   void __g__();
> %MethodCode
>   std::cout << "G: " << sipCpp << std::endl;
> %End
> 
>   int g;
> };
> 
> // end code
> 
> (the source files are also attached to the message)
> 
> Thus each class X in python has a __X__() method which prints its C++
> address, and a number of classes have an int data to check the value.
> 
> Now if we run this python test:
> 
> import test
> 
> def print_all(x, methods='abcdefg'):
>     for att in methods:
>         m = getattr(x, '__%s__' % att, None)
>         if m:
>             m()
>     print()
>     for att in methods:
>         m = getattr(x, '%s' % att, None)
>         if m:
>             print('%s:' % att, m)
> 
> g = test.G()
> 
> print_all(g)
> 
> 
> This test outputs, using sip 4.19.21 to 4.19.25:
> 
> A: 0x36fd720
> B: 0x36fd720
> C: 0x36fd720
> D: 0x36fd738
> E: 0x36fd738
> F: 0x36fd720
> G: 0x36fd720
> 
> a: 7
> b: 7
> c: 7
> d: 4
> g: 7
> 
> As you see object parts A, B, C, F and G all have the same address in 
> the
> bindings, whereas they obviously do not have the same address in C++ 
> (A, B
> and C are not related). Moreover as the offsets of virtual tables and 
> data
> in the object are wrong, the int values are wrong for most of them (a, 
> b
> and c all seem to contain 7 whereas they should contain 1, 2 and 3).
> 
> Using sip 4.19.15, the output of the same code was:
> 
> A: 0x1f72ed8
> B: 0x1f72ee8
> C: 0x1f72ec8
> D: 0x1f72eb8
> E: 0x1f72eb8
> F: 0x1f72ea0
> G: 0x1f72ea0
> 
> a: 1
> b: 2
> c: 3
> d: 4
> g: 7
> 
> which is totally correct.
> 
> In the sip code, if I remove the inheritance from C in F (just in the 
> sip
> code, not changing anything in the C++ part), then things become right 
> for
> a G object (using sip 4.19.25 again):
> 
> A: 0x31b5798
> B: 0x31b57a8
> C: 0x31b5788
> D: 0x31b5778
> E: 0x31b5778
> F: 0x31b5760
> G: 0x31b5760
> 
> a: 1
> b: 2
> c: 3
> d: 4
> g: 7
> 
> But obviously an instance of F will now be missing its A, B and C 
> parts.
> 
> After trying all this I remember that we have had possibly similar 
> problems
> in the first releases of sip 4.19:
> https://www.riverbankcomputing.com/pipermail/pyqt/2019-February/041313.html
> I haven't tested with the same example yet, so I'm not sure it's the 
> same
> problem which has re-appeared.
> 
> Thanks for your help,
> Denis
-------------- next part --------------
A non-text attachment was scrubbed...
Name: classes.sip
Type: application/octet-stream
Size: 1243 bytes
Desc: not available
URL: <https://www.riverbankcomputing.com/pipermail/pyqt/attachments/20211222/544c3be0/attachment.obj>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: classes.h
Type: text/x-chdr
Size: 597 bytes
Desc: not available
URL: <https://www.riverbankcomputing.com/pipermail/pyqt/attachments/20211222/544c3be0/attachment.h>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: classes.cpp
Type: text/x-c++src
Size: 256 bytes
Desc: not available
URL: <https://www.riverbankcomputing.com/pipermail/pyqt/attachments/20211222/544c3be0/attachment.cpp>


More information about the PyQt mailing list