0

アイテムのリストを維持するためにメモリを動的に割り当てていますが、を使用してアイテムを削除しようとするとfree()、メモリヒープの破損エラーが発生します。そして、これはC ++(またはJava、または実際には他のオブジェクト指向言語)で行う方がはるかに簡単であることを私は知っていますが、これはCで行う必要があります(注:Cコードですが、Microsoft VisualStudio2010でコンパイルされています。したがって、C ++コンパイラ)。

アイテムの「外観」は次のとおりです。

//item.h
typedef struct 
{
    char* titel;
    char* auteur;
    int jaar;
} Boek;

typedef struct
{
enum {BOEK, TIJDSCHRIFT} itemType;
    union {
        Boek* boek;
        Tijdschrift* tijdschrift;
    } itemData;
    struct Item* next;
} Item;

作成/割り当て方法は次のとおりです。strdupまた、文字列の割り当てに使用とmalloc/を切り替えましstrcpyたが、効果がないようです。また、私が削除しようとしているアイテムはBOEKタイプですが、TIJDSCHRIFTアロケータ/デアロケータは同じように機能します。

//item.c
Item* nieuwBoek(char* _titel, char* _auteur, int _jaar)
{
    Item* item = (Item*) malloc(sizeof(Item*));
    item->itemType=BOEK;
    item->itemData.boek=(Boek*) malloc(sizeof(Boek*));
    item->itemData.boek->titel=strdup(_titel);
    item->itemData.boek->auteur=strdup(_auteur);
    item->itemData.boek->jaar=_jaar;
    item->next=NULL;
    return item;
}

item->next返されたポインタは、リスト内の前の項目のに渡す別の関数によって使用されます。

これが私がそれを解放しようとしている方法です。構造体自体を解放する前に、割り当てられた文字列を解放する必要があることは理解していますが、free(item)を呼び出すだけでも(他のコードをコメントアウトするかdeleteItem、メインコードで呼び出すことによってfree(nieuwBoek(...):ヒープ破損エラー。

void deleteItem(Item* item)
{
    if (item->itemType==BOEK)
    {
        free(item->itemData.boek->titel); // When not running in debug-mode it crashes here.
        free(item->itemData.boek->auteur);
        free(item->itemData.boek); // When running in debug mode it crashes here.
    }
    /*else if... TIJDSCHRIFT deallocator here*/
    free(item); 
}

また、渡されるポインターdeleteItem()は、アイテムを指す有効なポインターです。それはおそらく私が間違っている/行方不明にしている信じられないほど愚かなことですが、私は今日この問題に困惑しているので、皆さんに助けを求めています。ああ、アイテムを削除する前ににnext->pointer設定されNULLているので、それが重要な場合は、リストからすでに切断されています。

4

3 に答える 3

3
Item* item = (Item*) malloc(sizeof(Item*));

またはに変更する必要がありsizeofます。それ以外の場合は、ポインタを保持するのに十分なだけ割り当てますが、構造にはほとんど十分ではありません。sizeof(Item)sizeof(*item)

個人的には好きsizeof *itemです。そうすれば、タイプを変更した場合でも、1か所で行うだけで済みます。


サイドノート:

  • 破損の意味:メモリをほとんど割り当てていないため、構造体フィールドに入力して内部の簿記を台無しにしたときにmalloc、次の操作でそれが検出されました
  • 個人的な好みの問題ですが、おそらくのリターンをキャストするべきではありませんmalloc
于 2012-07-28T17:00:15.910 に答える
2

これ:

Item* item = (Item*) malloc(sizeof(Item*));

ポインタに十分なスペースのみを割り当てます。Item構造全体に十分なスペースを割り当てる必要があります。

Item* item = (Item*) malloc(sizeof(Item));

同様に、この割り当て:

item->itemData.boek=(Boek*) malloc(sizeof(Boek*));

する必要があります:

item->itemData.boek=(Boek*) malloc(sizeof(Boek));
于 2012-07-28T17:00:45.207 に答える
0

パーティーへの投稿が遅れましたが、このタイプの問題はValgrindで検出されました。私はこの問題を抱えていました。GCCはプログラムの実行を許可しましたが、VC2012は毎回クラッシュするため、私は夢中になりました。Valgrindは次のことを示しました。

    サイズ8の無効な書き込み
        0x10CC33で:appendListItem(structMgmt.c:170)
        0x10BB6Eによる:解析(parse.c:304)
        0x10A790による:runParsingTests(CTSLicense.c:562)
        0x109B7Fによる:メイン(CTSLicense.c:41)
    アドレス0x5207748は、サイズ8のブロックが割り当てられた後の0バイトです。
        0x4C2CB3Fで:malloc(/usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so内)
        0x10CC2Aによる:appendListItem(structMgmt.c:169)
        0x10BB6Eによる:解析(parse.c:304)
        0x10A790による:runParsingTests(CTSLicense.c:562)
        0x109B7Fによる:メイン(CTSLicense.c:41)

これは非常に紛らわしいものでした(私はCを2週間知っています)。構造体の代わりにポインタのmallocを誤って持っていました。これで、私のプログラムはGCCとVC2012で問題なく実行されます。

Microsoftのページヒープ検出ツールを使用しても、問題の根本的な原因を見つけるのにあまり役立ちませんでした。表示されていた他の愚かなエラーの代わりにヒープの破損があったことはわかりましたが、問題の原因ではありませんでした。

Microsoftのヒープ検出ツール

この問題を見つけるためにvalgrindを使用するためのヒント

于 2017-03-24T17:48:18.183 に答える