释放分配的内存(C)时堆损坏



我正在动态分配内存以维护项目列表,但当尝试使用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,所以它已经从列表中断开了连接,如果这很重要的话。

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

您应该将sizeof更改为sizeof(Item)sizeof(*item)。否则,您将只分配足够容纳一个指针的空间,而不足以容纳您的结构。

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


旁注:

  • 损坏意味着什么:由于您分配的内存很少你填写了结构字段,搞砸了内部记账malloc,下一次操作检测到
  • 尽管这是个人偏好的问题,但你可能不应该投malloc的回报

这:

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));

派对后期发布,但Valgrind检测到了此类问题。我遇到了这个问题,这让我抓狂,因为GCC会允许程序运行,但VC2012每次都会崩溃。Valgrind显示如下:

大小为8的写入无效位于0x10CC33:appendListItem(structMgmt.c:170)由0x10B6E:解析(parse.c:304)0x10A790:runParsingTests(CTSLicense.c:562)通过0x109B7F:main(CTSLicense.c:41)地址0x5207748在分配大小为8的块之后为0字节位于0x4C2CB3F:malloc(在/usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so中)由0x10CC2A:appendListItem(structMgmt.c:169)由0x10B6E:解析(parse.c:304)0x10A790:runParsingTests(CTSLicense.c:562)通过0x109B7F:main(CTSLicense.c:41)

这非常令人困惑(我已经认识C两个星期了)。我不小心为指针而不是结构使用了malloc。现在我的程序在GCC和VC2012中运行,没有任何问题。

使用微软的页面堆检测工具并不能很好地找到问题的根本原因。它确实告诉我存在堆损坏,而不是出现的其他愚蠢错误,但不是问题的根源。

微软的堆检测工具

使用valgrind查找此问题的提示

相关内容

  • 没有找到相关文章

最新更新