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

结构体中使用动态数组的C代码问题:realloc触发后程序异常

问题分析与修复

你的代码主要有几个致命问题导致触发扩容时程序崩溃,以下是具体错误点和修复方案:

1. 扩容后主函数的指针未更新

addCar函数中,car_list是按值传递的局部变量,realloc返回的新内存地址仅在函数内部有效,主函数里的原始指针仍然指向已经被释放的旧内存块。后续通过旧指针访问内存会直接触发未定义行为(程序崩溃)。

修复方案:将addCar的参数改为指针的指针,让函数能直接修改主函数中的指针:

int addCar(struct _Car_List_** car_list, int id, char* name)
{
    struct _Car_* car = createCar(id, name);
    if (!car) return -1; // 新增检查car是否创建成功

    struct _Car_List_* list = *car_list;
    if (list->number_of_cars_ == list->max_number_of_cars_)
    {
        list->max_number_of_cars_ += SIZE;
        // 先保存realloc结果,避免原指针丢失
        struct _Car_List_* new_list = realloc(list, sizeof(struct _Car_List_) + list->max_number_of_cars_ * sizeof(struct _Car_*));
        if (!new_list)
        {
            free(car); // 避免内存泄漏
            return -1;
        }
        *car_list = new_list; // 更新主函数的指针
        list = new_list;
    }

    list->cars_[list->number_of_cars_] = car;
    list->number_of_cars_++;
    return 0;
}

调用时需要传递指针的地址:

addCar(&car_list, 1, "A");
// ... 其他addCar调用同理

2. realloc的错误检查逻辑完全错误

原代码中用if (car_list->cars_ == NULL)判断扩容是否失败,这是错误的:

  • 如果realloc失败,会返回NULL,此时car_list已经是NULL,访问car_list->cars_会直接触发空指针解引用崩溃。
  • 正确的做法是直接判断realloc的返回值是否为NULL。

3. 打印函数的循环越界

printCars函数中,循环逻辑错误:先取元素再自增i,当i等于number_of_cars_时,仍然会访问car_list->cars_[i],这时候已经超出数组的有效范围,会导致非法内存访问。

修复方案:调整循环逻辑,先检查i的范围再取元素:

void printCars(struct _Car_List_* car_list)
{
    for (int i = 0; i < car_list->number_of_cars_; i++)
    {
        struct _Car_* car = car_list->cars_[i];
        printf("- %s [%d]\n", car->name_, car->id_);
    }
}

其他潜在问题(建议修复)

  • createCar中直接赋值字符串指针:如果传入的是动态分配的字符串,后续释放时容易出现问题。建议改为字符串拷贝(需要包含<string.h>):
struct _Car_* createCar(int id, char* name)
{
    struct _Car_* car = malloc(sizeof(struct _Car_));
    if (!car) return NULL;

    car->name_ = strdup(name);
    if (!car->name_) { free(car); return NULL; }
    car->id_ = id;

    return car;
}
  • 缺少内存释放逻辑:程序结束时未释放分配的内存,会造成内存泄漏。建议添加清理函数:
void freeCarList(struct _Car_List_* car_list)
{
    if (!car_list) return;
    for (int i = 0; i < car_list->number_of_cars_; i++)
    {
        free(car_list->cars_[i]->name_); // 如果用了strdup则需要释放
        free(car_list->cars_[i]);
    }
    free(car_list);
}

在main函数末尾调用:freeCarList(car_list);

完整修正代码

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define SIZE 3

struct _Car_
{
    char* name_;
    int id_;
};

struct _Car_List_
{
    int number_of_cars_;
    int max_number_of_cars_;
    struct _Car_* cars_[];
};

struct _Car_* createCar(int id, char* name)
{
    struct _Car_* car = malloc(sizeof(struct _Car_));
    if (!car) return NULL;

    car->name_ = strdup(name);
    if (!car->name_) { free(car); return NULL; }
    car->id_ = id;

    return car;
}

int addCar(struct _Car_List_** car_list, int id, char* name)
{
    struct _Car_* car = createCar(id, name);
    if (!car) return -1;

    struct _Car_List_* list = *car_list;
    if (list->number_of_cars_ == list->max_number_of_cars_)
    {
        list->max_number_of_cars_ += SIZE;
        struct _Car_List_* new_list = realloc(list, sizeof(struct _Car_List_) + list->max_number_of_cars_ * sizeof(struct _Car_*));
        if (!new_list)
        {
            free(car->name_);
            free(car);
            return -1;
        }
        *car_list = new_list;
        list = new_list;
    }

    list->cars_[list->number_of_cars_] = car;
    list->number_of_cars_++;
    return 0;
}

void printCars(struct _Car_List_* car_list)
{
    for (int i = 0; i < car_list->number_of_cars_; i++)
    {
        struct _Car_* car = car_list->cars_[i];
        printf("- %s [%d]\n", car->name_, car->id_);
    }
}

void freeCarList(struct _Car_List_* car_list)
{
    if (!car_list) return;
    for (int i = 0; i < car_list->number_of_cars_; i++)
    {
        free(car_list->cars_[i]->name_);
        free(car_list->cars_[i]);
    }
    free(car_list);
}

int main()
{
    struct _Car_List_* car_list = malloc(sizeof(struct _Car_List_) + SIZE * sizeof(struct _Car_*));
    car_list->number_of_cars_ = 0;
    car_list->max_number_of_cars_ = SIZE;
    printf("Num of cars = %d\n", car_list->number_of_cars_);

    addCar(&car_list, 1, "A");
    printf("Num of cars = %d\n", car_list->number_of_cars_);

    addCar(&car_list, 2, "B");
    printf("Num of cars = %d\n", car_list->number_of_cars_);

    addCar(&car_list, 3, "C");
    printf("Num of cars = %d\n", car_list->number_of_cars_);
    
    addCar(&car_list, 4, "D");
    printf("Num of cars = %d\n", car_list->number_of_cars_);

    printCars(car_list);

    freeCarList(car_list);
    return 0;
}

内容的提问来源于stack exchange,提问作者3nondatur

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.01 10:15:02