I am developing a custom exception, where I'd need a QString member. Something like:
class MyException
{
private:
const QString fDescription;
public:
MyException(QString desc);
};
MyException::MyException(QString desc) : fDescription(desc)
{}
When I try to use it:
if (isErrorEncountered)
{
MyException e(QString("Descriptive message here..."));
throw e;
}
I get a segmentation fault. The symptoms are similar as described here: Qt QString cloning Segmentation Fault
The SIGSEGV originates from QBasicAtomicInt::ref
, coming from QString::QString(const QString &other)
.
It seems to me as if there is an attempt to copy an invalid QString within a copy constructor. It is my understanding, that the QString keeps a pointer to its content as long as there is a valid reference to it. If a copy of MyException instance is being made, is it not true that the temporary stack instance has not left the scope and the copy should succeed?
When I implement MyException
without a QString member, everything work well.
The answer to the question is "Yes, a QString can safely be a member in an exception."
The problems which I encountered were due to the fact that the object, acting as a source of data for the
fDescription
, had a bug. It implemented a getter method:Of course, the result of this call was the random value residing on the stack at the moment and hence the SIGSEGV.
The QString behaves as expected and with a valid reference to it, there are no problems using it in the exception.
The precise point where the SIGSEGV was raised was leaving the scope of the
try
block, where a copy of the exception is being constructed (remember: throw by value, catch by reference). The default copy constructor tries to create a shallow copy of all members and fails on accessing the invalid QString reference.