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
相关产品推荐
相关产品推荐

