2

我正在开发一个自定义异常,我需要一个 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 实例的副本,那么临时堆栈实例是否没有离开范围并且副本应该成功?

当我在MyException没有 QString 成员的情况下实现时,一切正常。

4

1 回答 1

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 引用。

于 2012-05-29T11:52:56.993 回答