0

我正在动态分配内存以维护项目列表,但是在尝试使用 删除项目时free(),出现内存堆损坏错误。而且我知道这在 C++(或 java,或任何其他面向对象的语言)中会容易得多,但我必须在 C 中执行此操作(注意:C 代码,但在 Microsoft Visual Studio 2010 中编译,并且因此是 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;

这是它的创建/分配方式。我还在使用strdupmalloc/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*));

您应该将其更改sizeofsizeof(Item)or sizeof(*item)。否则,您将仅分配足够的空间来容纳指针,而对于您的结构来说还不够。

我个人更喜欢sizeof *item- 这样如果我改变它的类型,我只需要在一个地方做。


旁注:

  • 腐败意味着什么:由于您分配的内存很少,当您填写结构字段以弄乱内部簿记时malloc,下一个操作检测到它
  • 尽管是个人喜好问题,但您可能不应该将 returnmalloc
于 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 的 pageheap 检测工具对于查找问题的根本原因并不是很有帮助。它确实告诉我存在堆损坏而不是出现的其他愚蠢错误,但不是问题的根源。

微软的堆检测工具

使用 valgrind 查找此问题的提示

于 2017-03-24T17:48:18.183 回答