2

私はQtが初めてです。そこで、開始例の 1 つであるlinkを再実装し始めました。

ただし、ウィンドウを閉じると SIGABRT シグナルが発生します。この理由は明らかに、何らかのメモリ管理エラーによるものです。

以下に、コールスタックと関連コードを示します。行editWindow.setLayout(&layout);がエラーの原因です。レイアウト クラスは破棄時にウィジェットを削除するため、それらの所有権を主張していますか?

この動作の理由は何ですか? そして、それを修正する方法は?

よろしくお願いします。

情報
コールスタック
コールスタック

ソース

  QPushButton testButton("Test");

  QVBoxLayout layout;
  layout.addWidget(&testButton);

  QWidget editWindow;
  // the following line is the source of the error
  editWindow.setLayout(&layout);
  editWindow.show();

  int val = app.exec();
4

3 に答える 3

7

多くの異なるQt関数は、渡されるオブジェクトの所有権を取得します。つまり、すべてのメモリ管理を制御し、削除時に解放します。setLayoutドキュメントから:

QWidgetがレイアウトの所有権を取得します。

呼び出した後setLayout、親があり、メソッドのスタックがクリーンアップされるときに削除されることに加えて、その親がそれを削除します。したがって、2回削除されているため、問題が発生しています。

他のすべてが正しければ、この変更で修正されるはずです。

QVBoxLayout *layout = new QVBoxLayout();
//...
layout->addWidget(&testButton);
//...
editWindow.setLayout(layout);

また、メインウィジェットを作成してから、そのウィジェットに表示されるウィジェットを親として割り当てるのが一般的であることに注意してください。言い換えれば、私は次のようなものを期待します(厳密には必要ではありませんが)。これは、将来何かが親に戻された場合でも問題が発生しないことを保証するのにも役立ちます。

QWidget editWindow;
QVBoxLayout *layout = new QVBoxLayout();
QPushButton *testButton = new QPushButton(&editWindow);
layout->addWidget(testButton);
editWindow.setLayout(layout);
editWindow.show();
int val = app.exec();

親が変更され、所有権の変更が発生する可能性のあるほとんどのQtオブジェクトには、QWidget*またはを受け入れるコンストラクターがありますQObject*

于 2011-07-14T16:45:16.517 に答える
2

QWidget演算子 new によって作成されたレイアウト インスタンスを想定し、インスタンスの所有権を取得して、QWidgetが破棄されたときに削除を呼び出します (ドキュメントを参照してください)。したがって、必要なものは次のようなものです。

QVBoxLayout *layout = new QVBoxLayout();
/// ...
editWindow.setLayout(layout);

所有権と同じことが testButton にも当てはまります。

于 2011-07-14T16:37:20.270 に答える
1

サンプルコードは間違っているようです (奇妙なことに)。レイアウト上のQWidget呼び出しのデストラクタ。deleteあなたの場合、QVBoxLayoutインスタンスはヒープではなくスタック上に作成されているためdelete、そのポインターを呼び出すと無効になり、アプリケーションが中止されます。

a のすべての子についても同様QObjectです。QObjectが削除されると、そのすべての子が呼び出されdeleteます。これらの子がスタック上に作成されている場合は、同じように失敗します。

ここで、Nokia がこのような悪い例を投稿した理由を理解するために...

于 2011-07-14T16:40:01.390 に答える