2

私たちはQt 4.8で作業していますが、正直なところ、これはQt 4.8とは何の関係もないと信じています(ただし、念のために指摘します)

コンパイルは問題なく実行できますが、実行時に次のエラーでクラッシュするこのクラスを作成しました。

*エラー: 53:01 Windows が C_plus_plus_QT_project.exe でブレークポイントをトリガーしました。これは、ヒープの破損が原因である可能性があります。これは、C_plus_plus_QT_project.exe または読み込まれた DLL のバグを示しています。これは、C_plus_plus_QT_project.exe にフォーカスがあるときにユーザーが F12 を押したことが原因である可能性もあります。出力ウィンドウには、より多くの診断情報が表示される場合があります。*

問題は、QFrame m_FrameHeader; です。.h ファイルとクラス コンストラクターで宣言されています。

QFrame m_FrameHeader(this);

正直なところ、これがコンパイルされることに驚いています。これがテストであり、結果がどうなるか誰かが私に尋ねたとしたら、変数の再定義、あいまいさ、またはそれらの線に沿った何かのために、これはコンパイルされないだろうと答えたでしょう。しかし、これは完全にコンパイルされ、実行時にクラッシュし、前述のヒープ破損エラーが発生します。

なぜそれがコンパイルされ、クラッシュすると、スタックエラーではなくヒープ破損エラーとしてクラッシュするのか、誰でも説明できますか? なぜスタックではなくヒープなのですか? 私はすでに問題を解決しました (正常にビルドされ、正常に実行されます) が、私が期待していたものではなく、なぜこのように動作するのか説明できませんでした (コンパイルエラーであり、それが間違っている場合は、ヒープではなくスタックエラー)

現在Qtをいじっているので、コードが悪いと予想しているため、その品質には注意を払っていません。それを無視してください (目前の問題の一部であると思わない限り、その場合は必要なだけ指摘してください (笑))。

私たちの環境: Qt 4.8.2、VS2010、Windows 7 x64。

これは.hです

#include <QtGui\QWidget>
#include <QtGui\QLabel>
#include <QtGui\QHBoxLayout>
#include <QtGui\QVBoxLayout>
#include <QtGui\QGridLayout>
#include <QtGui\QFrame>

class Quiniela : public QWidget
{
private:
    QLabel m_Fecha;
    QLabel m_Titulo;
    QLabel m_Hora;
    QHBoxLayout m_HeaderLayout;
    QFrame m_FrameHeader;
    QHBoxLayout m_SorteosLayout;
    QHBoxLayout m_EntesLayout;
    QGridLayout m_MainLayout;
public:
    Quiniela(int w = 800, int h = 600,QWidget* parent = 0);
    ~Quiniela();
};

これは.cppです

#include "Quiniela.h"
#include "FramePrincipal.h"
#include "Utils.h"

Quiniela::Quiniela(int w, int h, QWidget * parent)
    : QWidget(parent)
{
    Utils objUtil;
    QFont fontHead("Arial", 24, QFont::Black);
    QFont fontSorteos("Arial", 20, QFont::Normal);
    resize(w,h);
    setWindowTitle("QUINIELA");
    QFrame m_FrameHeader(this);
    m_FrameHeader.setGeometry(0,0,800,50);
    m_Fecha.setText(objUtil.getDate());
    m_Fecha.setFont(fontHead);
    m_Titulo.setText("*** QUINIELA ***");
    m_Titulo.setFont(fontHead);
    m_Hora.setText(objUtil.getTime());
    m_Hora.setFont(fontHead);
    m_HeaderLayout.addWidget(&m_Fecha,0,Qt::AlignLeft);
    m_HeaderLayout.addWidget(&m_Titulo,0,Qt::AlignCenter);
    m_HeaderLayout.addWidget(&m_Hora,0,Qt::AlignRight);
    m_HeaderLayout.setAlignment(Qt::AlignTop);
    m_FrameHeader.setLayout(&m_HeaderLayout);
}

Quiniela::~Quiniela()
{
}
4

3 に答える 3

2

Qt オブジェクトにはポインターを使用する必要があります (Qt はポインターを介してオブジェクトの親子リンクを維持し、親の削除時に子を破棄します)。あなたの例では、 m_FrameHeader はコンストラクターが返すときに破棄されます。これは、ローカル変数として宣言されているためです。

于 2012-06-14T20:22:13.037 に答える
1

問題は、ヒープに直接割り当てられていないオブジェクトの削除です。

最初は、クラス内に配置するウィジェットにQuinielaは親がありません。

最終的にそれらをm_headerLayoutレイアウトにインストールすると、レイアウトを設定したウィジェットに親が変更されます。

この行は、とm_FrameHeader.setLayout(&m_HeaderLayout)の親を に設定します。m_Fecham_Titulom_Horam_FrameHeader

m_FrameHeaderは、行で定義したローカルのスタック割り当て変数であることに注意してくださいQFrame m_FrameHeader(this)Quinielaコンストラクタの最後でスコープ外になります。子を持つ QObject が破棄されるとdelete、すべての子で呼び出されます。しかし、これらの子、具体的m_Fechaにはm_Tituloおよびm_Horaは、 を使用してヒープに割り当てられていませんnew

class member の非表示の間違いを修正してもm_FrameHeader、クラッシュは修正されません。のインスタンスが破棄されるまで単に遅延されますQuiniela

これを修正する唯一の方法は、すべてのウィジェットをヒープに割り当てることです。ウィジェットは次のようになります。

class Quiniela : public QWidget
{
private:

    QLabel * m_Fecha;
    QLabel * m_Titulo;
    QLabel * m_Hora;
    QHBoxLayout * m_HeaderLayout;
    QFrame * m_FrameHeader;
    QHBoxLayout * m_SorteosLayout;
    QHBoxLayout * m_EntesLayout;
    QGridLayout * m_MainLayout;
    ...

};

これらのオブジェクトを明示的に削除する必要はありません。Quiniela ウィジェットのインスタンスに再ペアレント化されるため、Qt が自動的に実行します。

于 2012-06-15T02:48:36.550 に答える
1

QFrame m_FrameHeader(this)m_FrameHeader という新しい (ローカル) 変数が宣言されているため、コンパイラ エラーは発生しません。これにより、同じ名前のクラス変数を隠しているという警告がコンパイラから生成されますそうではなかったと思いますか?とにかく、コンストラクターが戻ると m_FrameHeader が破棄されるため、クラッシュが発生しますが、破棄されていないものによってまだ参照されています。m_HeaderLayout など。

于 2012-06-14T20:29:23.287 に答える