You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

购物清单程序动态内存分配异常:malloc返回NULL导致崩溃求助

购物清单程序动态内存分配问题解决

核心错误分析

你的代码存在三个致命错误,直接导致内存分配失败或程序崩溃:

  1. 内存分配类型完全错误
    memoryAllocator函数中,你为struct ShoppingList类型分配内存,但实际需要分配的是struct GroceryItem数组(因为ShoppingList的itemList成员是指向GroceryItem的指针)。错误的类型大小计算会导致内存空间不足或分配错误的内存块。

  2. 函数参数传递类型不匹配
    在addItem中调用memoryAllocator时,你传入的是list->itemList(struct GroceryItem*类型),但函数期望的是struct ShoppingList**类型,这会导致指针地址混乱,realloc无法正确识别原有内存块。

  3. 内存分配结果判断逻辑颠倒
    代码中当temp != NULL(内存分配成功)时,反而输出错误并返回0终止流程;而分配失败(temp == NULL)时却认为成功,这完全搞反了判断逻辑。

修正后的关键代码

1. 修正memoryAllocator函数

// 修改函数参数类型为struct GroceryItem**,匹配itemList的类型
int memoryAllocator(struct GroceryItem** ListInMemory, int length) {
    struct GroceryItem* temp;

    if (length == 0) {
        // 分配1个GroceryItem大小的内存块
        temp = (struct GroceryItem*)calloc(1, sizeof(struct GroceryItem));
    } else {
        // 重新分配length+1个GroceryItem大小的内存块
        temp = (struct GroceryItem*)realloc(*ListInMemory, (length + 1) * sizeof(struct GroceryItem));
    }

    // 正确判断:temp为NULL则分配失败
    if (temp == NULL) {
        printf("内存分配失败,请重试\n");
        return 0;
    } else {
        *ListInMemory = temp;
        return 1;
    }
}

2. 修正addItem中的调用方式

void addItem(struct ShoppingList* list)
{
    int error = 0;
        
    // 传入itemList的地址,类型为struct GroceryItem**
    error = memoryAllocator(&list->itemList, list->length);
    if (error == 0)
        return;

    enterProductName(list);
    negativeCheck(list);
    enterUnit(list);
    
    printf("商品已添加!\n\n");
    list->length = list->length + 1;
    return;
}

3. 其他补充修正

  • saveList函数中free内存后,需要将itemList置为NULL,避免野指针:
void saveList(struct ShoppingList *list)
{
    free(list->itemList);
    list->itemList = NULL;
    list->length = 0;
}
  • itemDeleter函数中,删除元素后可以选择重新分配内存缩小空间(可选优化):
void itemDeleter(struct ShoppingList* list, int deleteThis) {
    int idx = deleteThis - 1;
    if (idx < 0 || idx >= list->length) return;

    for (int i = idx; i < list->length - 1; i++) {
        list->itemList[i] = list->itemList[i + 1];
    }
    list->length--;

    // 可选:缩小内存空间,避免浪费
    struct GroceryItem* temp = realloc(list->itemList, list->length * sizeof(struct GroceryItem));
    if (temp != NULL) {
        list->itemList = temp;
    }
}

测试验证

修正后,首次添加商品时calloc会分配1个GroceryItem的内存,后续添加时realloc会扩展内存到length+1个元素,内存分配成功判断逻辑正确,不会再触发错误终止或空指针崩溃。

内容的提问来源于stack exchange,提问作者Ted Boman

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.16 07:10:32