2017-11-02 23 views
1

最初のMainWindowがメインで開き、2番目の ウィンドウを開こうとすると、SIGABRTでプログラムがクラッシュします。 デバッガは次の行を示しています。私は同じことを行う場合はQt :: WA_DeleteOnCloseは、プログラムの動作属性と 設定しない場合、デストラクタの後で新しいQMainWindowクラッシュを開く

double free or corruption (out): 0x00007fffffffe340 *** 

RTTI symbol not found for class 'QObject' 
RTTI symbol not found for class 'QObject' 
RTTI symbol not found for class 'QObject' 
RTTI symbol not found for class 'QObject' 
RTTI symbol not found for class 'QObject' 
RTTI symbol not found for class 'QObject' 
RTTI symbol not found for class 'QObject' 

私はデストラクタを呼び出すための正しい方法だかを理解したいと 2番目のウィンドウでは(IE iは2番目のQMainwindowの3番目のウィンドウを開きます)、プログラムはQt :: WA_DeleteOnClose属性を設定しても機能します。最初のQMainWindowでのみ行うことはできませんか?メイン? Qtので

MainWindow::MainWindow(QWidget *parent) : 
    QMainWindow(parent), 
    ui(new Ui::MainWindow) 
{ 
    ui->setupUi(this); 
    this->setAttribute(Qt::WA_DeleteOnClose); 
    QTimer *t = new QTimer(this); 
    connect(t,SIGNAL(timeout()),this,SLOT(open_new())); 
    t->start(1000); 
} 

MainWindow::~MainWindow() 
{ 
    delete ui; 
} 

void MainWindow::open_new(){ 
    MainWindow2 *win_2 = new MainWindow2(0); 
    win_2->show(); 
    this->close(); 
} 
+0

これを削除できます。 – Taz742

+5

メイン()を表示してください。私は最初のMainWindowがスタック変数であると確信しています。 MainWindowが "new"演算子だけで作成されている場合、DeleteOnCloseを使うことができます。 – Matt

+0

http://doc.qt.io/qt-5/qguiapplication.html#quitOnLastWindowClosed-prop –

答えて

4

すべてQWidgetsは、このように管理されています

  1. すべてのデストラクタが仮想です。
  2. ウィジェット(実際にはQObject)に親がある場合、親はそれを(operator deleteを使用して)自分自身で削除します。つまり、すべての子ウィジェットはoperator newで作成するか、親が入る前に破棄する必要があります(@BenjaminTコメントを参照)。
  3. ウィジェットが親(すなわち0)を持っていないとclose信号を処理している間に属性が設定されWA_DeleteOnCloseた、それは、(メンバ関数deleteLater()を使用することにより、@BenjaminTコメントを参照してください)operator delete自身の呼び出しを開始する場合(実際にはdeleteが呼び出されます。まあ、後で、つまりスロットコードの内側にはありません。@DmitrySazonovコメントを参照してください)。繰り返しますが、(a)アプリケーションは冗長であるため、これを行うべきではありません。 (b)ウィジェットはまだoperator newで作成する必要があります。
  4. ウィジェットに親がなく、WA_DeleteOnClose属性が設定されていないウィジェットには、呼び出し元のアプリケーションの作成方法と消滅方法があります。たとえば、QWidgetがスタック変数である場合、対応する関数から返ってきたときに自動的に破棄されます(C++では普通です)。

場合によっては、最初のMainWindowはnew operatorで作成されていない可能性がありますので、WA_DeleteOnClose属性を設定してはいけません。しかし、次のコードは正常に動作するはずです:

int main(int argc, char* argv[]) 
{ 
    QApplication app(argc, argv); 
    MainWindow* w = new MainWindow(0); 
    // redundant if the attibute is set inside the class constructor 
    //w->setAttribute(Qt::WA_DeleteOnClose); 
    w->show(); 
    return app.exec(); 
} 
+1

ポイント3では、それは' delete this'を呼び出すのではなく、少し違う 'deleteLater()'を呼びます。 –

+0

ポイント2については、すべての子の 'QObject'を' new'で作成する必要はありません。唯一の制約は、 'new'で作成されていなければ、親の'〜QObject() 'デストラクタを呼び出す前にそれらを破壊しなければならないということです。特に、その親のメンバ変数として格納された 'QObject'を持つことが安全であることを意味します。 –

+0

@BenjaminTまあ、それは愚かな証明コードの一部です。 1日の終わりに 'delete'演算子が呼び出されます。 – Matt

関連する問題