我正在开发一个自定义异常,我需要一个QString成员。类似的东西:
class MyException
{
private:
const QString fDescription;
public:
MyException(QString desc);
};
MyException::MyException(QString desc) : fDescription(desc)
{}
当我尝试使用它时:
if (isErrorEncountered)
{
MyException e(QString("Descriptive message here..."));
throw e;
}
我遇到了分段错误。 症状与此处描述的类似: Qt QString cloning Segmentation Fault
SIGSEGV来自QBasicAtomicInt::ref
,来自QString::QString(const QString &other)
。
在我看来,似乎试图在复制构造函数中复制无效的QString。据我所知,只要有一个有效的引用,QString就会保留一个指向其内容的指针。如果正在创建MyException实例的副本,那么临时堆栈实例是否未离开范围并且副本应该成功是不是真的?
当我在没有QString成员的情况下实现MyException
时,一切正常。
答案 0 :(得分:1)
问题的答案是“是的,QString可以安全地成为异常中的成员。”
我遇到的问题是由于作为fDescription
的数据源的对象有错误。它实现了一个getter方法:
class Source
{
private: QString fData;
public: QString GetData(void) { this->fData; } // There is a missing return
}
当然,这次调用的结果是当前驻留在堆栈上的随机值,因此也就是SIGSEGV。
QString按预期运行,并且对它有效引用,在异常中使用它没有问题。
引发SIGSEGV的确切点是离开try
块的范围,其中正在构造异常的副本(记住:按值抛出,按引用捕获)。默认的复制构造函数尝试创建所有成员的浅表副本,并在访问无效的QString引用时失败。