why does this crash?

M

Mr Fish

I don't understand why this crashes in the dtor of Info.

Can someone explain to me what I'm missing?

Thanks

//---------------------------------------------------------
struct Info
{
int* m_pData;

Info():m_pData(0){}
Info(int* pData):m_pData(pData)
{}

~Info(){if (m_pData) delete m_pData;}
};

class Base
{
protected:

Info m_SomeInfo;

public:

virtual ~Base(){}
};


class Derived : public Base
{
public:

Derived(){m_SomeInfo = Info(new int(5));}
};



int main()
{
Derived d;

return 0;
}

//------------------------------------------------------
 
P

PasalicZaharije

In class Derived at line:

m_SomeInfo = Info(new int(5));

is error. With this, m_SomeInfo.m_pData will point on same location like
temporary created with Info(new int(5)). So:

Info(new int(5)).m_pData is same pointer as
m_SomeInfo.m_pData.

This will not crach your programm but after destructor is called
everithing is down. First is called destructor for Info(new int(5)) in
ctor Derived(), than in main. Both destructors will try to erase same
memory.

To prevent this, make operator = in class Info:

struct Info
{
int* m_pData;

Info():m_pData(0){}
Info(int* pData):m_pData(pData) {}

Info& operator=(const Info&) {
if (this != &Info) { // we do not need self assignment
// allocate m_pData an copy
// Info.m_pData in it
}
return *this;
}

~Info(){if (m_pData) delete m_pData;}
};

Probably, you will need and copy ctor like:

Info(Info &i) {
// allocate and copy
}



Best,Zaharije Pasalic
 
K

Karl Heinz Buchegger

Mr said:
I don't understand why this crashes in the dtor of Info.

Can someone explain to me what I'm missing?

Rule of three:
If a class needs a custom destructor, it most likely also needs a
custom copy constructor and a custom assignment operator.

Your class Info falls into this category.

What is going on:
Derived(){m_SomeInfo = Info(new int(5));}

Info( new int(5))

A single int is generated (with the value 5 in it)



o------------>+------+
| 5 |
+------+

and a pointer to it is passed in the constructor of the temporary
Info object. The constructor does:
Info(int* pData):m_pData(pData)

i.e. stores this pointer

temporary Info object
+-----------+
| m_pData |
| o------------+
+-----------+ |
|
+----------+
|
+--->+------+
| 5 |
+------+

What's next? Then comes the assignment in

m_SomeInfo = Info(new int(5)

Since you didn't write an assignment operator on your own, the
compiler generated one for you, which does:

Info& Info::eek:perator=( const Info& Arg )
{
m_pData = Arg.m_pData;
}

That is: a memberwise assignment of all members.
Well in your case, this boils down to:

temporary Info object
+-----------+
| m_pData |
| o------------+
+-----------+ |
|
+----------+
|
+--->+------+
+--->| 5 |
| +------+
|
+--------------+
|
Derived |
+---------------------+ |
| | |
| Base | |
| +----------------+ | |
| | m_SomeInfo | | |
| | +------------+ | | |
| | | m_pData | | | |
| | | o---------------+
| | +------------+ | |
| +----------------+ |
+---------------------+

That is: The m_pData pointer in m_SomeInfo inside Base points
to the same int as the temporary Info object does.

Well. A few nanoseconds later, the temporary info object ceases to
exist. It's destructor is called, which does:

~Info(){if (m_pData) delete m_pData;}

(The if is not necessary. You can safey delete a 0 pointer).
Thus the temporary object deletes the int it has allocted just
before itself gets wiped out of memory. This leaves you with:

+--->
|
|
+--------------+
|
Derived |
+---------------------+ |
| | |
| Base | |
| +----------------+ | |
| | m_SomeInfo | | |
| | +------------+ | | |
| | | m_pData | | | |
| | | o---------------+
| | +------------+ | |
| +----------------+ |
+---------------------+


Ooops. The pointer m_pData in m_SomeInfo now points to nowhere
in memory. So when finaly that Derived object gets destroyed, all
destructors are run, especially the dtor of m_SomeInfo which tries
to delete .... hmm ... nothing sensible. There is no data anymore
where the pointer is pointing to. -> Claboom.

Google for 'Rule of three C++'
and should find enough references on how to cure this thing.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,764
Messages
2,569,565
Members
45,041
Latest member
RomeoFarnh

Latest Threads

Top