C语言多指针指向同一地址问题 结构体指针数组存CSV数据故障求解
问题根因
你遇到的两个问题核心都是错误引用了栈上临时内存的地址,具体如下:
- 所有数组元素指向同一个栈地址
- 循环内部定义的
data_t customer是栈局部变量,每次循环都会复用同一块栈内存,循环结束后这块内存会被系统回收。你先malloc了结构体堆内存,又直接把array[index]赋值为&customer,不仅造成了内存泄漏,还让所有数组元素都指向同一个栈地址,最终这个地址里保留的是最后一次循环写入的值,所以打印所有元素都和最后一个元素内容一致。
- name字段无法正常打印
strtok返回的是临时缓冲区buffer内部的指针,buffer同样是栈上的临时内存,每次循环都会被新读取的CSV行覆盖,循环结束后buffer内容失效,所以name字段指向的是无效内存,无法输出正确内容。
修复后完整代码
#include <stdio.h> #include <stdlib.h> #include <string.h> typedef struct data data_t; struct data { char *name; int id; double balance; }; int main(int argc, char **argv) { FILE *fp = NULL; // 最多存10条数据,可根据需求调整 data_t **array = (data_t **) malloc(10 * sizeof(data_t *)); if (argc < 2) { printf("No file input\n"); exit(1); } // 修复原代码运算符优先级错误,加括号保证先执行fopen赋值再判空 if ((fp = fopen(argv[1], "r")) == NULL) { printf("File not found\n"); exit(1); } char buffer[128]; char delim[2] = ","; int index = 0; while(fgets(buffer, 128, fp) && index < 10) // 加边界判断避免数组越界 { // 先解析当前行的所有字段 char *name = strtok(buffer, delim); int id = atoi(strtok(NULL, delim)); double balance = atof(strtok(NULL, delim)); // 给当前结构体分配堆内存 array[index] = (data_t *) malloc(sizeof(data_t)); // 字符串单独分配内存复制内容,不要直接引用buffer的指针 array[index]->name = strdup(name); array[index]->id = id; array[index]->balance = balance; index += 1; } fclose(fp); fp = NULL; // 测试打印代码 for (int i = 0; i < index; i++) { printf("第%d条:name=%s, id=%d, balance=%.2f\n", i+1, array[i]->name, array[i]->id, array[i]->balance); } // 内存释放逻辑,避免泄漏 for (int i = 0; i < index; i++) { free(array[i]->name); free(array[i]); } free(array); return 0; }
核心修复要点
- 不要把动态分配的结构体指针指向栈局部变量,直接把解析到的字段值赋值到堆内存的结构体成员中
- 字符串类型的成员需要单独分配内存复制内容,可直接用
strdup完成分配+复制的操作,如果环境不支持strdup可以替换为malloc(strlen(name)+1)加strcpy的实现 - 补充了数组越界防护和原代码中fopen判断的运算符优先级错误,避免异常崩溃
内容的提问来源于stack exchange,提问作者StoneForest
相关产品推荐
相关产品推荐

