0

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

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

然后,一个结构体来表示数据输入对话框中的项目数据

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

现在,从主窗口的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()数据转储,整个事情就会按预期工作。

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

  • 这个没有解决
  • 这个解决方案不适用于我的情况

我在这里做错了什么?

4

1 回答 1

1

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

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

qDebug 创建一个相当大的缓冲区——当你踩到它时不会让你的程序崩溃

在重写的过程中,我得到了这种行为:当我的函数没有返回值时,qDebug()是在“拯救”它们免于崩溃。在强制所有函数返回一个值后,崩溃停止了。

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

于 2017-01-12T12:29:39.687 回答