C语言单/双指针正确使用:Record数组读取后main中值乱码问题
问题分析与解决方案
核心问题1:指针传递方式错误
你当前的load_array函数接收的是Record*类型的指针参数,这是值传递——函数内部的array_of_records是外部指针的副本。当realloc需要重新分配内存时,新的内存地址只会赋值给函数内部的局部指针,而main函数里的原始指针array_of_records依然指向旧的内存地址(如果realloc释放了旧内存,这个指针就变成野指针),所以main里访问的是已经失效的内存,打印出垃圾值。
必须使用**指针的指针(双指针)**作为参数,让load_array能直接修改main中的指针变量。
核心问题2:字符串内存被提前释放
你在load_array里刚把malloc出来的string_field赋值给结构体成员,就立刻调用free(string_field),这会导致结构体的string_field变成悬空指针——指向的内存已经被释放,后续任何访问都是未定义行为,必须将这个free操作推迟到结构体不再使用的时候执行。
修改后的完整代码
结构体定义(不变)
typedef struct Record{ int id; char* string_field; int int_field; double double_field; } Record;
main函数修改
#include <stdio.h> #include <stdlib.h> #include <string.h> int main(int argc, char const *argv[]){ if(argc < 2){ printf("Usage: ordered_array_main <file_name>\n"); exit(EXIT_FAILURE); } int capacity = 2; Record* array_of_records = NULL; array_of_records = (Record*)malloc(capacity * sizeof(Record)); // 传递指针的地址给load_array int size = load_array(argv[1], &array_of_records, capacity); // 打印第一个元素验证 if(size > 0){ printf("%d, %d\n", array_of_records[0].id, array_of_records[0].int_field); } // 先逐个释放结构体中的字符串内存,再释放数组本身 for(int i = 0; i < size; i++){ free(array_of_records[i].string_field); } free(array_of_records); return 0; }
load_array函数修改
#include <stdio.h> #include <stdlib.h> #include <string.h> // 参数改为Record**,接收指针的地址 int load_array(const char* file_name, Record** array_of_records, int capacity){ int index_of_record = 0; FILE* fp = fopen(file_name, "r"); if(fp == NULL){ fprintf(stderr, "Failed to open file\n"); exit(EXIT_FAILURE); } char buffer[1024]; char* field[4]; while(fgets(buffer, sizeof(buffer), fp)!=NULL){ // 分割字符串(补全省略的strtok逻辑) field[0] = strtok(buffer, ","); field[1] = strtok(NULL, ","); field[2] = strtok(NULL, ","); field[3] = strtok(NULL, "\n"); int id_field = atoi(field[0]); char *string_field = malloc((strlen(field[1])+1)* sizeof(char)); strcpy(string_field, field[1]); int int_field = atoi(field[2]); double double_field = atof(field[3]); if(index_of_record >= capacity){ Record* tmp = NULL; // 解引用双指针,获取原始指针的地址 tmp = (Record*)realloc(*array_of_records, 2*capacity*sizeof(Record)); if(tmp==NULL){ fprintf(stderr, "Memory allocation failure\n"); exit(EXIT_FAILURE); } // 更新原始指针的值 *array_of_records = tmp; capacity = 2*capacity; } // 解引用双指针,操作数组元素 (*array_of_records + index_of_record)->id = id_field; (*array_of_records + index_of_record)->string_field = string_field; (*array_of_records + index_of_record)->int_field = int_field; (*array_of_records + index_of_record)->double_field = double_field; printf("%d\n", (*array_of_records + index_of_record)->int_field); index_of_record++; // 移除这里的free(string_field)! } fclose(fp); return index_of_record; }
内容的提问来源于stack exchange,提问作者tpip_enjoy
相关产品推荐
相关产品推荐

