2012-07-31 4 views
0

참조 된 변수 src_의 속성을 참조 할 때 프로그램이 종료됩니다. 코드의 주요 개념은 MainWindow 클래스가 SettingsWindow 클래스를 호출하여 일부 설정을 표시한다는 것입니다. 저장된 설정을 처리하는 추가 클래스가 두 개 있습니다.이 클래스는 ConfigSource 및 ConfigUpdater입니다. src_은 ConfigUpdater에서 참조되는 변수로 정의됩니다. 내가 액세스하려고 할 때참조 변수에 액세스하면 프로그램이 종료됩니다.

#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); 

이 부분은 중요하다 : 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 헤더 및 소스 여기 코드는 src_ 슬롯 적용 및 취소에서 프로그램 종료, 예 :

_tempconfig 변수를 인쇄해도 문제가 없습니다. 단순화를 위해 헤더 파일에서 일부 단추 슬롯을 제거했습니다.

이 버그를 해결하는 방법을 나에게 보여 주면 내가 감사합니다 :)

+0

당신이 받고있는 오류와 그것을 일으키는 약간의 코드를 보여주십시오. 문제를 복제하고 격리하는 짧은 예가 훨씬 더 좋을 것입니다. 임시 참조를 사용하는 것 같습니다. – AJG85

답변

1

ConfigSource 객체가 MainWindow 생성자에서 지역 변수로 생성된다, 그래서 그 생성자의 끝과 다른 모든 참조에 파괴 무효가된다.

수명을 늘리기 위해 MainWindow의 멤버로 선언 할 수 있습니다.

2

ConfigSource cfg;MainWindow의 생성자에 국한됩니다.

충돌이 발생한 슬롯을 호출하는 신호가있을 때 MainWindow 생성자는 (심지어 MainWindow 인스턴스가 여전히있는 경우에도) 실행이 오래 끝났기 때문에 참조가 더 이상 유효하지 않습니다.

0

다른 두 답변이 잘 설명합니다 (ConfigSource cfg;은 MainWindow의 생성자에 로컬이므로 생성자가 완료된 후 메모리가 회수됩니다).

수정 - 이전에이 질문을 할 때했던 것처럼 (운영자 new를 통해) 사용 힙 할당

+0

MainWindow에서 ConfigSource를 정의하는 것이 좋습니다. ConfigUpdater 클래스에서 해당 참조를 사용하면 src_의 임시 값이 유지된다는 것을 알고 있습니다. MainWindow 생성자 내에서 초기 지점을 선언했는데, MainWindow가 파손되거나 사용자에 의해 닫히기 전에 최신 설정 src_ 값을 FILE로 업데이트 할 수 있기 때문입니다! 구조와 코드를 깔끔하게 만드는 더 좋은 아이디어가 있습니까? –

+0

이것은 틀린 것입니다. MainWindow가 파손되거나 사용자에 의해 닫히기 전에 MainWindow 생성자 내부의 첫 번째 점을 선언했습니다. MainWindow 생성자가 종료되고 내부에서 선언 된 내용이 모두 파손되므로이 창을 닫는 사용자와 아무 관계가 없습니다. , 나중에 발생합니다. 덕분에 – jahhaj

1

당신은 본질적으로 같은 문제가 있습니다.

이전 ConfigSource는 SettingsWindow 생성자에 대해 로컬이므로 너무 일찍 파괴되었습니다. 이제 ConfigSource는 MainWindow 생성자에 대해 로컬이므로 MainWindow 생성자가 종료 될 때 파괴되지만 너무 빠릅니다! ConfigSource 개체는 적어도 SettingWindow 개체만큼 길어야합니다. 한 가지 방법은 ConfigWindow 개체 내에 ConfigSource 개체를 넣는 것이지만 그렇게하고 싶지는 않다는 것을 기억하는 것 같습니다. 또 다른 방법은 Main에 ConfigSource 객체를 선언하여 (프로그램이 살아있을 때까지), SettingWindow 생성자에 대한 참조를 통해 전달하는 것입니다.

코드의 구조를 알고있는 경우에만 개체의 수명에 대한 핸들을 가져와 ConfigWizard 개체가 적어도 SettingWindow 개체만큼 길어야한다는 것을 기억해야합니다.당신은 정말로이 생각을 당신 머리에서 똑바로 얻을 필요가 있습니다. 그렇지 않으면 당신은이 문제들을 많이 겪게 될 것입니다.

+0

. 메인 윈도우 클래스 나 메인 프로그램 내에서 ConfigSource를 선언하는 것이 어떤 차이점도 없다고 생각합니다. 주 창은 항상 사용자가 닫을 수있는 마지막 창입니다. 또는 Settings 클래스 내부에 있습니까? –

+0

MainWindow 클래스의 SettingsWindow 클래스에서 주 기능에서이 세 곳 중 하나가 작동한다고 생각합니다. – jahhaj

+0

감사합니다 Jahhaj :) –

관련 문제