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

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);
    }

问题根源

  1. 未为parameters分配独立内存:所有结构体的parameters大概率指向了同一块静态内存或未正确分配的内存区域,后续写入操作直接覆盖了之前的数据。
  2. 非法内存访问:代码中gate[numinstruct].parameters[gate[numinstruct].size];属于无效操作,且未给parameters分配内存就直接访问下标,必然触发崩溃或非法内存访问。
  3. 变量逻辑混乱:同时使用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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.09 15:35:16