0

私はこれについて頭を悩ませています。これは、私だけが見ることができれば本当に簡単な答えがある問題の1つか、あいまいな落とし穴の1つです。問題は、ある関数で構造体オブジェクトを新規作成し、ポインターをデキューに保存し、そのポインターを別の関数で取得し、構造体のデータが使用されたら、ヒープ上のオブジェクトを削除しようとしていることです。すべてが 1 つのクラス インスタンスで発生します。それをすると、私は爆弾を手に入れます。理由がよくわかりません。これは、作成時および取得後の有効なポインターです。書き込み/読み取りができます。しかし、それを削除しようとすると、da bomb が発生します。

//This creates and saves the heap object
void CFoo::QueueEvent( TICKTYPE& tp )
{

    TICKTYPE* pTt = new TICKTYPE;

    memcpy( pTt, &tp, sizeof(tp) );

    m_queuedevents.push_front( pTt );

}

//This retrieves it
int CFoo::ReplayQueuedEvents()
{
    long lSz = m_queuedevents.size();

    for( int i = 0; i < lSz; i++ )
    {
        TICKTYPE Tt;

        TICKTYPE* pTt = m_queuedevents.back();
        //m_queuedevents.pop_back();   //bombs w or w/o this

        //bombs w ot w/o memcpy
        memcpy( &Tt, pTt, sizeof( *pTt ) );

        //int iRtn = SendEvent( Tt );

        ASSERT( SendEvent( Tt ) != ERR_FAILURE );

        //This asserts before or after the memcpy.
        delete[] pTt;
        //delete pTt;

    }

}

パート2

ご提案いただきありがとうございます。

削除[]と削除

私は必死だったので、delete[] も試してみましたが、それはたまたまコピーしたものでした。私は2か所で削除を試みましたが、それでも動作します。

「TICKTYPEを表示」

私は TICKTYPE を表示しますが、今見てみると、内部に少なくとも 2 つの他の構造体への参照があり、かなり単純なものからかなり複雑なものに成長しています。数ページのコードを投稿(およびフォーマット)する必要があります。以下のコメントに基づいて、それをクラッシュの原因として調べてみます。ありがとうございました。

「削除する前に pTt が有効かどうかを確認してください。」

削除する前に読み書きを試みましたが、すべて問題ないようです。また、Vis Stud は、削除する直前に構造体に有効なデータを表示します。これをさらに研究するときは、これを念頭に置いておきます。

「3のルール」

ああ、まあそうかもしれません。

まだ解決策はありませんが、解決したら投稿します。皆さんは良いアイデアをいくつか提供してくれました。もう頭を悩ませることはありません。ひざまずいて仕事をするだけです。乞うご期待...

再度、感謝します。(PS 'da bomb' は通常は良いことですが、英語の美しさは、単語を構成しても要点を伝えることができることです' より正確ではあるが退屈な用語は、GPF、ASSERT などでした。対処するときにこれらが必要です。ときどき C++ を使って... :) ここでコーディングの心理学について話す人は誰もいません..笑.")

パート 3

問題はmemcpyにあることがわかりました。すべての memcpy を取り出すと、オブジェクトが削除されます。ただし、コピーの問題が残ります。参照 TICKTYPE& tp からポインター TICKTYPE*​​ pTt に移動する必要があります (QueueEvent を参照)。

以下のクールな提案に従って Copy コンストラクターを作成してみました。この問題は、次のような従来の copy-ctor が使用されている場合に返されます。

TICKTYPE( TICKTYPE const& ref )
{
    a = ref.a;
    b= ref.b;
    c = ref.c;
    d= ref.d;
    e = ref.e;  //etc...
}

メイン構造体の内部にはディープ コピーされる構造体がいくつかあり、MSFT 構造体の FILETIME と SYSTEMTIME がいくつかありますが、それらが既にコピー ctor を持っているかどうかはわかりません。

次に、ref から ptr への移行の問題があります。署名入りコピー機をやってみた

TICKTYPE*​​ ref;

それから

pTt = rTt

ここで、pTt は TICKTYPE*​​ で、rTt は TICKTYPE rTt です。それはコンパイルされませんでした。

質問

他の構造体を含む構造体を ref から新しいポインター var (スタックからヒープ) にコピーする最良の方法は何ですか? より永続的なストレージのために、そのデータをスタックからヒープに移動したいと考えています。

memcpy によってコピーされた構造体にストラットが埋め込まれないように、各構造体レベルの mem コピーを行うことを考えていました。どう思いますか?良いアプローチですか?

パート 4

回答者の皆様に改めて感謝いたします。あなたのアドバイスは非常に役に立ちました。この問題は、最上位構造体の memcpy を実行するときに作成されました。メインの最上位構造体の内部で下位構造体の memcpy を実行しても、下位構造体がない限り、delete が失敗することはありませんでした。下位の構造体で memcpy を使用し、最上位の構造体で変数コピーによる変数を使用しました。こんな感じです

TYPE1 foo1;

foo1.a = foo.a
foo1.b = foo.b
foo1.c = foo.c
memcpy( foo1.d, foo.d, sizeof( foo.d) );
memcpy( foo1.e, foo.e, sizeof( foo.e) );

それはうまくいきます。他の方法ほどエレガントではないかもしれませんが、当分の間機能するか、機能するように見えます。すべてがメインコード本体に明確に文書化されており、何が起こっているのか、その利点があります。

4

2 に答える 2

4

ではなくdelete[] pTt;で割り当てたため、未定義の動作が発生します。を使用します。newnew[]delete

すでに試したことがある場合は、3 のルールに従わなかった可能性があります (ググってください)。は、一部のリソースの所有権をローカルと にmemcpy( &Tt, pTt, sizeof( *pTt ) );分散させる可能性があります。範囲外になると、そのデストラクタが呼び出されます。そして、delete を呼び出すときのデストラクタです。デストラクタが同じリソースを解放しようとすると、クラッシュが発生します。TtpTtTtpTt

この場合は使用しないでくださいmemcpy。コピー コンストラクターを使用します。

TICKTYPE Tt = *pTt;
于 2013-10-23T23:09:33.647 に答える