[solved] Destructor called twice and causes app crash
-
Problem: Passing variable to emit signal which is of simple class (not QObject). This class has destructor which deletes allocated pointers - as I understood this is mandatory for non QObject class - right?
However inside of handling function on_bnScanStop_clicked() this destructor is called twice for some reason. (Or one more constructor missing?) . This causes app to crash when trying to delete non existing variable.
Any clue how to deal with this?
@
"cfiledat00.h"
class CFileDat00
{ public:
CFileDat00();
~CFileDat00();
CARMVrefItem *armvref;
}"cfiledat00.cpp"
CFileDat00::CFileDat00()
{
qDebug() << "CFileDat00 contructor";
armvref = new CARMVrefItem(12,34,56);
}
CFileDat00::~CFileDat00()
{
qDebug() << "CFileDat00 destructor";
delete armvref;
}"mainwindow.cpp"
void MainWindow::on_bnScanStop_clicked()
{
qDebug() << "on_bnScanStop_clicked enter";
CFileDat00 filtmp;
filtmp.scango->setHexval(0);
emit sig_writef00(filtmp);
qDebug() << "on_bnScanStop_clicked exit";
}
@
The debug output of this code:
@
on_bnScanStop_clicked enter
CFileDat00 contructor
CFileDat00 destructor
on_bnScanStop_clicked exit
CFileDat00 destructor
@Edit by sierdzio: added code tags
-
Is this signal connected to a thread, or does it use Qt::QueuedConnection?
The signal emission most probably creates a copy of the object (using default copy constructor - so pointers in both object point to the same thing!), so the destructor is called twice, once for your filtmp and second time for the copy.
-
Up to this point signal is not connected to anywhere. It was initial intention to have filtmp copy in the signal. This is why I passed the object itself and not a pointer. I was expecting to see one more constructor - of a copy. But looking more broadly - why and how can destructor be called if constructor has never been called?
-
Implicit copy constructor was called: this is the constructor that is created automatically by your compiler. It does not contain your debug statement for obvious reasons. To avoid it's creation, you can use "Q_DISABLE_COPY":http://qt-project.org/doc/qt-5/qobject.html#Q_DISABLE_COPY
Or you can explicitly create your own copy constructor and handle the situation there. There are, of course, other options available, too: you can stop deleting the pointer in the destructor. Or you can change that CARMVrefItem into a stacked variable.
-
ok, that explains things a bit why second constructor is not seen on debug. But why then this second destructor tries to kill the original filtmp and not its copy which was created by compiler Implicitly.
Now it looks like both filtmp and its implicit copy inside signal has same pointer what in turn appears to be same object and not copy? -
To understand that, we need some background on pointers. When you define a pointer member in your class, all that is actually stored there is a (usually) 32 bit integer value that points to the real object in memory. That is why you can do something like this:
@
SomeClass *pointer = 0;
// ...if (pointer) {
// ...
}
@So, when the default copy constructor encounters a pointer, it will copy that number. It will not attempt to create a copy of the object that the pointer refers to.
Then, when your destructor calls delete it no longer works on that number; it goes directly to the object in question, and calls it's destructor. The other object (the one you emit) attempts to do exactly the same thing, but the object it attempts to delete from memory is no longer there.
-
bq. when the default copy constructor encounters a pointer, it will copy that number. It will not attempt to create a copy of the object that the pointer refers tobq.
This almost explain everything. Now remains question how to force compiler to create true copy of that object not just another set of pointers? In other words how to make it call real constructor?
-
You've got 2 options here:
create your own copy constructor where you do all the things you want to
create your member variables on a stack, not on heap (that is: don't use pointers)
-
You are welcome, happy coding :-)