0

参照されている変数src_のプロパティを参照すると、プログラムが終了します。このコードの主な考え方は、MainWindowクラスがSettingsWindowクラスを呼び出していくつかの設定を表示することです。保存された設定を処理する2つの追加クラスもあります。それらはConfigSourceとConfigUpdaterです。src_は、ConfigUpdater内の参照変数として定義されています。コードは次のとおりです。

MainWindow内:

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 は SettingsWindow コンストラクターに対してローカルであったため、破棄が早すぎました。現在、ConfigSource は MainWindow コンストラクターに対してローカルであるため、MainWindow コンストラクターが終了すると破棄されますが、これはまだ時期尚早です! ConfigSource オブジェクトは、少なくとも SettingWindow オブジェクトと同じくらい存続する必要があります。1 つの方法は、ConfigSource オブジェクトを SettingsWindow オブジェクト内に配置することですが、それをやりたくないことを覚えているようです。もう 1 つの方法は、メインで ConfigSource オブジェクトを宣言し (そのため、プログラムが存続する限り存続します)、SettingWindow コンストラクターへの参照を介して渡すことです。

コードの構造を知っているのはあなただけです。オブジェクトの存続期間を把握する必要があります。また、ConfigSource オブジェクトは少なくとも SettingWindow オブジェクトと同じ期間存続する必要があることを覚えておいてください。このアイデアを頭の中で真っ直ぐに理解する必要があります。そうしないと、これらの問題に何度も遭遇することになります。

于 2012-07-31T20:55:57.330 に答える
1

ConfigSourceオブジェクトはコンストラクターでローカル変数として作成されるため、そのMainWindowコンストラクターの最後で破棄され、他のすべての参照が無効になります。

のメンバーとして宣言してMainWindow、寿命を延ばすことができます。

于 2012-07-31T20:29:58.447 に答える
0

他の2つの答えはこれをうまく説明していConfigSource cfg;ます(MainWindowのコンストラクターに対してローカルであるため、コンストラクターの終了後にメモリが回収されます)。

修正 - ヒープ割り当てを使用 ( operator 経由new)

于 2012-07-31T20:32:33.733 に答える