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

C语言动态数组地址传参错误导致程序崩溃,求解决方案

问题修复说明

核心错误点

  • 参数类型不匹配:main函数中调用readDataFromFile时传入的是二级指针&listProduct(类型为struct Product **),但readDataFromFile定义的第一个参数为struct Product *,类型错位导致所有后续指针操作都访问非法内存。
  • realloc参数传值错误:insertProduct中调用realloc时,第一个参数需要传入动态数组原首地址(即*listProduct),但代码直接传入了二级指针listProduct,直接触发内存访问违规,是程序崩溃的直接原因。
  • 缺少异常校验:未判断fopen的返回值,如果目标文件不存在、无读取权限,fopen返回NULL后直接调用fgets也会触发崩溃。
  • 格式符使用不规范:打印指针地址应该使用%p格式化符,使用%d会出现地址截断、类型不匹配的问题。

修复后代码

main函数

int main(int argc, char** argv) {
    struct Product* listProduct = malloc(sizeof(struct Product) * 1); 
    printf("address of listProduct in main: %p \n", &listProduct);
    int length = 0;
    char fileName[] = "products.txt";
    length = readDataFromFile(&listProduct,length,fileName);    
    
    printf("address of listProduct in main after insert: %p \n", &listProduct);
    printf("length in main %d \n", length);
    printf("start for in main \n");
    int i;
    for(i =0; i < length; i++){
        printf("%s \n", listProduct[i].tenSanPham);
    }
    // 释放动态内存避免泄漏
    free(listProduct);
    printf("end for in main \n");   
    return 0;
}

readDataFromFile函数

int readDataFromFile(struct Product** listProduct,int length, char fileName[]){
    printf("address of listProduct in readData: %p \n", *listProduct);
    FILE *fp;
    char buff[1024];
    struct Product product;
    fp = fopen(fileName, "r");
    // 新增文件打开失败校验
    if (fp == NULL) {
        perror("打开文件失败");
        return length;
    }

    while(fgets(buff, sizeof(buff), fp) != NULL){
        product = convertStringToProduct(buff);
        printf("IN readData: %s \n", product.tenSanPham);
        // 直接传入二级指针即可,无需额外取地址
        insertProduct(product, listProduct, length);
        length++;
    }
    fclose(fp); 
    int i ;
    printf("\n\ncheck value in listProduct after insert\n");
    for(i = 0; i < length; i++){
        // 二级指针需要先解引用再访问数组元素
        printf("IN FOREACH readData: %s \n", (*listProduct)[i].tenSanPham);
    }  
    printf("read done \n");
    return length;
}

insertProduct函数

void insertProduct(struct Product product, struct Product** listProduct, int length)
{
    printf("addres of listProduct in insert %p \n", *listProduct);
    printf("Product In Insert: %s \n", product.tenSanPham);
    // 用临时指针承接realloc返回值,避免扩容失败丢失原内存地址
    struct Product *temp = realloc(*listProduct, sizeof(struct Product) * (length+1));
    if (temp == NULL) {
        perror("扩容内存失败");
        return;
    }
    *listProduct = temp;
    (*listProduct)[length] = product;
    printf("Get product inserted: %s length: %d \n", (*listProduct)[length].tenSanPham, length);
    printf("insert done!\n");
}

额外优化说明

  • malloc、realloc的返回值在C语言中无需强制类型转换,void *可以隐式转换为任意指针类型,强转反而可能隐藏隐式声明的问题。
  • 动态内存使用完成后必须调用free释放,避免内存泄漏。
  • 读取文件时直接用sizeof(缓冲区变量)作为fgets的长度参数,避免硬编码错误。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.26 05:15:08