Re: Unusual usage of IUknown

Tech-Archive recommends: Speed Up your PC by fixing your registry



Gingko wrote:
"Scot T Brennecke" <ScotB@xxxxxxxxxxxxxxxxxx> a écrit dans le message de news: %23aAM18sKKHA.3708@xxxxxxxxxxxxxxxxxxxxxxx
A virtual destructor only helps to make sure the most-derived destructor is actually called. If this is a sub-object aggregated into another object, you've still got big trouble.

Ok.

I juste made a small test for checking that again (see below).
Whatever "this" pointer I use for deletion, the result is the same, and all destructors are called in the same order (which is the reverse of construction order).

But maybe I didn't make there a proper "sub-object aggregated into another object" ?
Of course I will never declare such objects as flat members of other objects (if needed, I'll use pointers to these objects, likely protected by CComPtr).

Please could you either modify my code or provide a sample in order to illustrate what you are saying ?

Gilles


------------------------------------------------


#include <iostream>

using namespace std;

// Just for easily checking what happens if you remove "virtual" in front of destructors
#define VIRTUAL virtual

class V
{
char * szData;
public:
V() : szData("V") {
cout << "calling V constructor, szData=" << szData << endl;
}
V * get_V_this() {
return this;}
VIRTUAL ~V() {
cout << "calling V destructor, szData=" << szData << endl;
}
};

class W : public virtual V
{
char * szData;
public:
W() : szData("W") {
cout << "calling W constructor, szData=" << szData << endl;
}
W * get_W_this() {
return this;}
VIRTUAL ~W() {
cout << "calling W destructor, szData=" << szData << endl;
}
};

class X : public virtual V
{
char * szData;
public:
X() : szData("X") {
cout << "calling X constructor, szData=" << szData << endl;
}
X * get_X_this() {
return this;}
VIRTUAL ~X() {
cout << "calling X destructor, szData=" << szData << endl;
}
};

class Y
{
char * szData;
public:
Y() : szData("Y") {
cout << "calling Y constructor, szData=" << szData << endl;
}
Y * get_Y_this() {
return this;}
VIRTUAL ~Y() {
cout << "calling Y destructor, szData=" << szData << endl;
}
};


class Z
{
char * szData;
public:
Z() : szData("Z") {
cout << "calling Z constructor, szData=" << szData << endl;
}
Z * get_Z_this() {
return this;}
VIRTUAL ~Z() {
cout << "calling Z destructor, szData=" << szData << endl;
}
};

class B : public W, public X, public Y
{
char * szData;
public:
B() : szData("B") {
cout << "calling B constructor, szData=" << szData << endl;
}
B * get_B_this() {
return this;}
VIRTUAL ~B() {
cout << "calling B destructor, szData=" << szData << endl;
}
};

class A : public Z, public B
{
char * szData;
public:
A() : szData("A") {
cout << "calling A constructor, szData=" << szData << endl;
}
VIRTUAL ~A() {
cout << "calling A destructor, szData=" << szData << endl;
}
};

int main(int argc, char * argv[])
{
A * ptA;

ptA = new A;
cout << "*** deleting A instance by A::this = 0x" << hex << ptA << endl;
delete ptA;
cout << "-----------------" << endl;
ptA = new A;
B * ptB = ptA->get_B_this();
cout << "*** deleting A instance by B::this = 0x" << hex << ptB << endl;
delete ptB;
cout << "-----------------" << endl;
ptA = new A;
V * ptV = ptA->get_V_this();
cout << "*** deleting A instance by V::this = 0x" << hex << ptV << endl;
delete ptV;
cout << "-----------------" << endl;
ptA = new A;
W * ptW = ptA->get_W_this();
cout << "*** deleting A instance by W::this = 0x" << hex << ptW << endl;
delete ptW;
cout << "-----------------" << endl;
ptA = new A;
X * ptX = ptA->get_X_this();
cout << "*** deleting A instance by X::this = 0x" << hex << ptX << endl;
delete ptX;
cout << "-----------------" << endl;
ptA = new A;
Y * ptY = ptA->get_Y_this();
cout << "*** deleting A instance by Y::this = 0x" << hex << ptY << endl;
delete ptY;
cout << "-----------------" << endl;
ptA = new A;
Z * ptZ = ptA->get_Z_this();
cout << "*** deleting A instance by Z::this = 0x" << hex << ptZ << endl;
delete ptZ;
return 0;
}


------------------------------------------------

Output when running the above code :

calling V constructor, szData=V
calling Z constructor, szData=Z
calling W constructor, szData=W
calling X constructor, szData=X
calling Y constructor, szData=Y
calling B constructor, szData=B
calling A constructor, szData=A
*** deleting A instance by A::this = 0x00367178
calling A destructor, szData=A
calling B destructor, szData=B
calling Y destructor, szData=Y
calling X destructor, szData=X
calling W destructor, szData=W
calling Z destructor, szData=Z
calling V destructor, szData=V
-----------------
calling V constructor, szData=V
calling Z constructor, szData=Z
calling W constructor, szData=W
calling X constructor, szData=X
calling Y constructor, szData=Y
calling B constructor, szData=B
calling A constructor, szData=A
*** deleting A instance by B::this = 0x00367180
calling A destructor, szData=A
calling B destructor, szData=B
calling Y destructor, szData=Y
calling X destructor, szData=X
calling W destructor, szData=W
calling Z destructor, szData=Z
calling V destructor, szData=V
-----------------
calling V constructor, szData=V
calling Z constructor, szData=Z
calling W constructor, szData=W
calling X constructor, szData=X
calling Y constructor, szData=Y
calling B constructor, szData=B
calling A constructor, szData=A
*** deleting A instance by V::this = 0x003671A0
calling A destructor, szData=A
calling B destructor, szData=B
calling Y destructor, szData=Y
calling X destructor, szData=X
calling W destructor, szData=W
calling Z destructor, szData=Z
calling V destructor, szData=V
-----------------
calling V constructor, szData=V
calling Z constructor, szData=Z
calling W constructor, szData=W
calling X constructor, szData=X
calling Y constructor, szData=Y
calling B constructor, szData=B
calling A constructor, szData=A
*** deleting A instance by W::this = 0x00367188
calling A destructor, szData=A
calling B destructor, szData=B
calling Y destructor, szData=Y
calling X destructor, szData=X
calling W destructor, szData=W
calling Z destructor, szData=Z
calling V destructor, szData=V
-----------------
calling V constructor, szData=V
calling Z constructor, szData=Z
calling W constructor, szData=W
calling X constructor, szData=X
calling Y constructor, szData=Y
calling B constructor, szData=B
calling A constructor, szData=A
*** deleting A instance by X::this = 0x00367190
calling A destructor, szData=A
calling B destructor, szData=B
calling Y destructor, szData=Y
calling X destructor, szData=X
calling W destructor, szData=W
calling Z destructor, szData=Z
calling V destructor, szData=V
-----------------
calling V constructor, szData=V
calling Z constructor, szData=Z
calling W constructor, szData=W
calling X constructor, szData=X
calling Y constructor, szData=Y
calling B constructor, szData=B
calling A constructor, szData=A
*** deleting A instance by Y::this = 0x00367180
calling A destructor, szData=A
calling B destructor, szData=B
calling Y destructor, szData=Y
calling X destructor, szData=X
calling W destructor, szData=W
calling Z destructor, szData=Z
calling V destructor, szData=V
-----------------
calling V constructor, szData=V
calling Z constructor, szData=Z
calling W constructor, szData=W
calling X constructor, szData=X
calling Y constructor, szData=Y
calling B constructor, szData=B
calling A constructor, szData=A
*** deleting A instance by Z::this = 0x00367178
calling A destructor, szData=A
calling B destructor, szData=B
calling Y destructor, szData=Y
calling X destructor, szData=X
calling W destructor, szData=W
calling Z destructor, szData=Z
calling V destructor, szData=V

All your examples do not exhibit any aggregation. I think you understand the potential problem if you had

class V
{
char * szData;
ULONG m_cRef;
public:
V() : szData("V") {}
VIRTUAL ~V() {}
ULONG STDMETHODCALLTYPE CUnknownStub::Release()
{
if (--m_cRef == 0) {
delete this;
return 0;
}
return m_cRef;
}
};

class W
{
V v;
char * szData;
public:
W() : szData("W") {}
VIRTUAL ~W() {}
};
.



Relevant Pages

  • Re: [C++] ctors & dtors
    ... (Use and Finish could be named constructor and destructor, ... I tried calling ~foo() directly and it crashed. ...
    (comp.programming)
  • Re: Shutdown order
    ... Thomas Mlynarczyk wrote: ... Where am *I* calling the destructor in my code? ... Like a constructor, you ...
    (comp.lang.php)
  • Re: Object passing
    ... crash MATLAB and/or your computer. ... Your constructor is ... calling something else which is calling the constructor ... classdef b < handle ...
    (comp.soft-sys.matlab)
  • Re: Unusual usage of IUknown
    ... ptA = new A; ... calling V constructor, szData=V ... calling A destructor, szData=A ...
    (microsoft.public.vc.language)
  • Re: gcc option for constructor and destructors
    ... I should register a routines which will be called before calling the ... function and destructor before actual return of the original function. ... Does gcc provides anything like this. ... To simulate a constructor, ...
    (comp.unix.programmer)