C语言动态结构体数组中内部数组值被后续值覆盖问题
动态结构体数组参数被覆盖问题的解决方案
问题描述
我是C语言新手,正在学习高效编码方式。目前尝试创建动态结构体数组,结构体定义如下:
struct dir { int size; int *parameters; };
读取文件内容时,将值存入临时字符数组vars2,通过二维字符串数组vars查找对应索引,未找到则新增至vars中。随后将结构体节点存入动态数组gates并重新分配内存,但发现结构体中parameters数组的值会被后续读取的指令覆盖,size变量却不受影响。
举个例子:
- 原指令1:
size = 2;param = {2, 3, 5} - 原指令2:
size = 3;param = {3, 6, 8}
循环外输出时,指令1的param被覆盖为{3, 6, 8},与指令2的param完全一致。
尝试直接向gates数组的结构体成员赋值时,程序在parameters部分崩溃,相关代码如下:
typedef struct { int size; int *parameters; } DIR; DIR *gate = malloc(1*sizeof*gate); // 中间代码省略 int numinstruct = 0; struct dir *gates = malloc(1*sizeof(struct dir)); while (fscanf(fp, "%s", gate) == 1) { struct dir node; // 中间代码:读取文件内容,为结构体size赋值,parameters为静态数组 gate[numinstruct].parameters[ gate[numinstruct].size]; for (i = 0; i < gate[numinstruct].size; i++) { fscanf(fp, " %16s", vars2); int index = indexLookup(vars, vars2, length); if (index != -1) { gate[numinstruct].parameters[i] = index; } else { vars = realloc(vars, (length+1)*sizeof(char*)); vars[length] = malloc(17*sizeof(char)); strcpy(vars[length], vars2); gate[numinstruct].parameters[i] = length; length++; } } numinstruct++; gates = realloc(gates, (numinstruct+1)*sizeof*gates); }
问题根源
- 未为
parameters分配独立内存:所有结构体的parameters大概率指向了同一块静态内存或未正确分配的内存区域,后续写入操作直接覆盖了之前的数据。 - 非法内存访问:代码中
gate[numinstruct].parameters[gate[numinstruct].size];属于无效操作,且未给parameters分配内存就直接访问下标,必然触发崩溃或非法内存访问。 - 变量逻辑混乱:同时使用
gate(单个结构体指针)和gates(结构体数组指针),导致内存操作逻辑混淆,容易出错。
修复步骤
1. 为每个结构体的parameters分配独立内存
处理每条指令时,先根据size为当前结构体的parameters分配足够内存:
// 假设node.size已从文件中正确读取 gates[numinstruct].size = node.size; gates[numinstruct].parameters = malloc(gates[numinstruct].size * sizeof(int)); if (gates[numinstruct].parameters == NULL) { perror("malloc failed"); exit(EXIT_FAILURE); }
2. 修正循环内的内存访问逻辑
删除无效的gate[numinstruct].parameters[gate[numinstruct].size];行,完成内存分配后再填充参数:
for (i = 0; i < gates[numinstruct].size; i++) { fscanf(fp, " %16s", vars2); int index = indexLookup(vars, vars2, length); if (index != -1) { gates[numinstruct].parameters[i] = index; } else { vars = realloc(vars, (length+1)*sizeof(char*)); if (vars == NULL) { perror("realloc failed"); exit(EXIT_FAILURE); } vars[length] = malloc(17*sizeof(char)); if (vars[length] == NULL) { perror("malloc failed"); exit(EXIT_FAILURE); } strcpy(vars[length], vars2); gates[numinstruct].parameters[i] = length; length++; } }
3. 优化结构体数组的内存分配逻辑
初始化gates时设为NULL,每次扩容用临时指针接收,避免内存泄漏:
int numinstruct = 0; struct dir *gates = NULL; // 用临时缓冲区存读取的字符串,避免破坏结构体内存 char temp_buf[17]; while (fscanf(fp, "%s", temp_buf) == 1) { // 先扩容结构体数组 struct dir *temp_gates = realloc(gates, (numinstruct + 1) * sizeof(struct dir)); if (temp_gates == NULL) { perror("realloc failed"); // 释放已分配的内存 for (int j = 0; j < numinstruct; j++) { free(gates[j].parameters); } free(gates); exit(EXIT_FAILURE); } gates = temp_gates; // 读取size等信息到node // ... // 为当前结构体的parameters分配内存 gates[numinstruct].size = node.size; gates[numinstruct].parameters = malloc(node.size * sizeof(int)); if (gates[numinstruct].parameters == NULL) { perror("malloc failed"); // 清理已分配内存 for (int j = 0; j <= numinstruct; j++) { free(gates[j].parameters); } free(gates); exit(EXIT_FAILURE); } // 填充参数(即上述修正后的for循环) // ... numinstruct++; }
4. 统一变量命名,避免混淆
删除冗余的gate指针,统一用gates表示结构体数组,用临时变量处理单个结构体的读取逻辑。
额外注意事项
- 所有
malloc/realloc操作后必须检查返回值是否为NULL,避免空指针访问。 - 程序结束前需释放所有分配的内存:先遍历
gates数组释放每个parameters,再释放gates本身,最后释放vars中的每个字符串和vars数组。 - 读取文件时,不要直接用
fscanf(fp, "%s", gate),会破坏结构体内存,应使用临时字符缓冲区存储读取的字符串。
内容的提问来源于stack exchange,提问作者Skyttlez
相关产品推荐
相关产品推荐

