0

当我引用引用变量 src_ 的属性时,我的程序终止。代码的主要思想是 MainWindow 类调用 SettingsWindow 类来显示一些设置。还有两个额外的类负责保存的设置,它们是 ConfigSource 和 ConfigUpdater。src_ 被定义为 ConfigUpdater 中的一个引用变量。这是代码:

在主窗口内:

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    ConfigSource cfg;

        settings = new SettingsWindow(cfg,this);

        settings->print_config(cfg.config());
...

SettingsWindow 标题和来源:

#ifndef SETTINGSWINDOW_H
#define SETTINGSWINDOW_H

#include <QMainWindow>
#include <QModelIndex>

#include <QSignalMapper>
#include <QRadioButton>
#include <QSpinBox>
#include <QTimer>

#include "cameracommands.h"

struct Config
{
    /* General Options */
    QString general_key_lock;
    QString general_back_light;
};

class ConfigSource 
{
    public:

    ConfigSource() {
        qDebug() << "inside configSource :))";
        config_.general_aperture_control   = "Reset";
        config_.general_automatic_exposure = "Full Auto";

    }

    Config config() const {return config_;}

    void setConfig(const Config& cfg) {config_ = cfg;}

//        Config config_;
    private:
    Config config_;
};

class ConfigUpdater : public QObject
{
    Q_OBJECT
public:
    ConfigUpdater(ConfigSource& src) : src_(src) {}

public slots:

    void apply () {src_.setConfig(tempConfig_);}
    void cancel() {tempConfig_ = src_.config();}

public:

    void updateGeneralBackLight(QString s)             {tempConfig_.general_back_light         = s; qDebug() << "BackLight updated :)";}
    void updateGeneralKeyLock(QString s)               {tempConfig_.general_key_lock           = s; qDebug() << "KeyLock updated :)";}

    Config tempConfig_;
    ConfigSource& src_;
};

//----------------------------

namespace Ui {
    class SettingsWindow;
}

class SettingsWindow : public QMainWindow
{
    Q_OBJECT

public:
    explicit SettingsWindow(ConfigSource &src, QWidget *parent = 0);

    ~SettingsWindow();

    void print_config(Config cfg);

signals:
    void clicked(const QString &text);
    void sendToPLC(QByteArray );

public slots:
    void updateGeneralBackLight();
    void updateGeneralKeyLock();

private:

    void set_mappings();

    Ui::SettingsWindow *ui;
    ConfigUpdater      *config_updater;
};

#endif // SETTINGSWINDOW_H

设置源文件

SettingsWindow::SettingsWindow(ConfigSource &src, QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::SettingsWindow)
{
    /* initializations */
    ui->setupUi(this);
    config_updater = new ConfigUpdater(src);

这部分很关键,当我尝试从应用和取消插槽访问 src_ 时,程序终止,例如:

void SettingsWindow::on_pushButton_3_clicked() //apply
{
    qDebug() << "Apply Button";

    print_config(config_updater->src_.config());
    config_updater->apply();
    print_config(config_updater->src_.config());
}

void SettingsWindow::print_config(Config config)
{
    qDebug() << config.general_key_lock;
    qDebug() << config.general_back_light;
}

void SettingsWindow::on_sendToMainButton_clicked() /* cancel */
{
   print_config(config_updater->tempConfig_);

   config_updater->cancel();

   print_config(config_updater->tempConfig_);

   print_config(config_updater->src_.config_);
}

不过,打印 _tempconfig 变量可以正常工作!为了简单起见,我从头文件中删除了一些按钮槽。

如果你告诉我如何解决这个错误,我会很感激 :)

4

4 回答 4

2

ConfigSource cfg;对于 的构造函数是本地的MainWindow

当负责调用发生崩溃的槽的信号时,MainWindow构造函数早已执行完毕(即使MainWindow实例还在),所以引用不再有效。

于 2012-07-31T20:30:05.607 回答
1

ConfigSource对象在构造函数中被创建为局部变量MainWindow,因此它在该构造函数的末尾被销毁,并且所有其他引用都变得无效。

您可以将其声明为成员MainWindow以增加其生命周期。

于 2012-07-31T20:29:58.447 回答
1

您遇到的问题与您之前提出此问题时遇到的问题基本相同。

早期的 ConfigSource 是 SettingsWindow 构造函数的本地,所以它被过早地销毁了。现在 ConfigSource 对 MainWindow 构造函数来说是本地的,所以当 MainWindow 构造函数退出时它会被销毁,但这还为时过早!ConfigSource 对象必须至少与 SettingWindow 对象一样长。一种方法是将 ConfigSource 对象放在 SettingsWindow 对象中,但我似乎记得您不想这样做。另一种方法是在 main 中声明 ConfigSource 对象(因此它与程序一样长)并通过对 SettingWindow 构造函数的引用将其传递下来。

只有您知道代码的结构,您只需要掌握对象的寿命,并记住 ConfigSource 对象的寿命必须至少与 SettingWindow 对象一样长。你真的需要把这个想法直接放在你的脑海里,否则你会经常遇到这些问题。

于 2012-07-31T20:55:57.330 回答
0

其他两个答案很好地解释了这一点(ConfigSource cfg;对于您的 MainWindow 的构造函数来说是本地的,因此在构造函数完成后内存会被回收)。

修复使用堆分配(通过 operator new

于 2012-07-31T20:32:33.733 回答