qDebug() 的奇怪行为导致应用程序崩溃

Weird behavior of qDebug() crashing the application

我一直在调试一个简单的目录应用程序,这个问题开始困扰我。我想创建一个模态对话框,它将接收用户对呈现数据的输入。我有一个保存目录项数据的简单结构:

struct ItemData {
    int nodeType;
    int nodeID;
    int nodeLevel;
    QString nodeName;
    QString nodeNote;
    QString fileName;
}

然后,在数据输入对话框中表示项目数据的结构

struct DialogData {
    QString name;
    QString note;
    QString file;
}

现在,从 window 的 editRec() 主要方法调用数据输入对话框:

void MainWindow::editRec()
{
    // model is defined in the main window, getSelectedRowData()
    // fills the struct with data properly
    ItemData md = model->getSelectedRowData(ui->treeView->selectionModel());

    // data, on wich the dialog will operate
    DialogData dd;

    dd.name = md.nodeName;
    dd.note = md.nodeNote;
    dd.file = md.fileName;

    // checking whether the data wich is being read from the model
    // and being passed to dialog is correct
    // qDebug '<<' operator is overloaded to handle my structs
//    qDebug << md;        // - outputs data properly, then crashes the program
//    qDebug << dd;        // - also, outputs data properly, then crashes the program

    // suspecting the error in the '<<' overload, I tried to output 
    // one field at a time and it works if I if uncomment one 
    // line at a time, but crashes the application if I try to 
    // output all fields in one go.
//  qDebug() << md.nodeType;
//  qDebug() << md.nodeID;
//  qDebug() << md.nodeLevel;
//  qDebug() << md.nodeName;
//  qDebug() << md.nodeNote;
//  qDebug() << md.fileName;

    DataDialog *dialog;

//  dialog's interface and data handling differs depending on 
//  the type of the node it will operate on
    switch (md.nodeType) {
    case NODE_ROOT: {
        dialog = new DataDialog(dlgEditRoot, false, this);
        dialog->setDialogData(dd, NODE_ROOT);
        break;
    }
    case NODE_BRANCH: {
        dialog = new DataDialog(dlgEditBranch, false, this);
        dialog->setDialogData(dd, NODE_BRANCH);
        break;
    }
    }
    dialog->initWidgets();
    if (dialog->exec() == QDialog::Accepted) {   // showing a modal dialog
        // if user changed the data, modifying the model with the new data
        if (dialog->isDataChanged) {             
            dd = dialog->getDialogData();
            switch (md.nodeType) {
            case NODE_ROOT: {
                md.nodeName = dd.name;
                md.nodeNote = dd.note;
                md.fileName = dd.file;
                model->setSelectedRowData(ui->treeView->selectionModel(), md);
                break;
            }
            case NODE_BRANCH: {
                md.nodeName = dd.name;
                md.nodeNote = dd.note;
                md.fileName = dd.file;
                model->setSelectedRowData(ui->treeView->selectionModel(), md);
                break;
            }
            }
        }
    }
    qDebug() << md;    // - both of these output data correctly without any crashes
    qDebug() << dd;    //
    delete dialog;
}

如果我注释掉前三个qDebug() 数据转储,整个过程将按预期工作。

我在 Whosebug 上只发现了两个有点相似的问题:

我做错了什么?

我开始使用 Kuba Ober 的建议进行挖掘,这使我对最初使用的整个数据结构进行了非常深入的重构,几乎是完全重写。虽然我没有找到我之前遇到的崩溃的确切原因,但我能够解决这个问题。

给可能遇到类似问题的人的一些提示。我在最初的问题中发布的 links 实际上与我的问题直接相关。第一个link,Scott 'scm6079'表示:

qDebug creates a fairly significant buffer -- which when stomped on won't crash your program

我在重写的过程中遇到了这种行为:当我的函数没有 return 值时,qDebug() 是 'saving' 它们的崩溃。在将所有函数强制为 return 一个值后,崩溃停止了。

接下来,如果您既不子类化 QObject 实体也不使用智能指针,请特别注意 new 以将它们与适当的 delete 匹配。不要在条件分支中创建变量。如果您需要根据条件创建对象,请将构造函数中的不同位重构为您将在创建后从条件分支调用的方法。虽然我不确定它是否是好的编码风格,但它确实帮助我修复了崩溃问题。