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

C语言如何正确为结构体数组执行realloc动态内存重分配

C语言动态扩容结构体数组问题修复

核心错误点

  • 初始容量计算错误:net_devicies是指针类型,sizeof(net_devicies)得到的是指针本身的字节数,不是数组长度,原初始容量计算完全失效。
  • 计数变量未递增:存储每条记录后没有给count加1,所有新输入的记录都会覆盖索引为0的位置,导致后续索引的内容都是未初始化的乱码。
  • 扩容逻辑时序错误:扩容操作对应的容量计数和实际存储的元素数量不匹配,导致分配的内存空间和实际需求不符。
  • 内存泄漏隐患:释放结构体数组前没有先释放每个元素中name字段申请的堆内存。
  • 缺少输入合法性校验:没有判断拆分后的参数数量是否为3,可能出现访问空指针的崩溃问题。

修复后的完整代码

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

// 补充get_str简单实现,若你已有对应实现可删除此部分
char* get_str() {
    static char buf[1024];
    if (fgets(buf, sizeof(buf), stdin) == NULL) return NULL;
    char *p = strchr(buf, '\n');
    if (p) *p = '\0';
    if (strlen(buf) == 0) return NULL;
    return strdup(buf);
}

typedef struct net_device {
    char IPv4[16];
    char isOnline[6];
    char *name;
} net_device;

int main () {
    struct net_device *net_devices = NULL;
    char *s = NULL;
    int count = 0; // 已存储的有效记录数
    int capacity = 0; // 数组当前总容量

    do {
        printf("Enter a new network device record: Name, IPv4, isOnline\n");
        s = get_str();
        if (s) {
            char **res = NULL;
            char *p = strtok(s, " ");
            int n_spaces = 0;
            
            while (p) {
                res = realloc(res, sizeof(char*) * ++n_spaces);
                if (res == NULL) exit(-1); 
                res[n_spaces-1] = p;
                p = strtok(NULL, " ");
            }
            res = realloc(res, sizeof(char*) * (n_spaces+1));
            res[n_spaces] = 0;

            // 输入合法性校验,必须有3个参数
            if (n_spaces < 3) {
                free(s);
                free(res);
                continue;
            }

            // 容量不足时每次扩容1个单位,符合逐输入扩容需求
            if (count == capacity) {
                capacity += 1;
                net_devices = realloc(net_devices, sizeof(struct net_device) * capacity);
                if (net_devices == NULL) exit(-1);
            }

            // 存储当前记录
            net_devices[count].name = malloc(strlen(res[0]) + 1);
            strcpy(net_devices[count].name, res[0]);    
            strncpy(net_devices[count].IPv4, res[1], sizeof(net_devices[count].IPv4)-1);
            net_devices[count].IPv4[sizeof(net_devices[count].IPv4)-1] = '\0';
            strncpy(net_devices[count].isOnline, res[2], sizeof(net_devices[count].isOnline)-1);
            net_devices[count].isOnline[sizeof(net_devices[count].isOnline)-1] = '\0';
            
            free(s);
            free(res);
            count++; // 计数+1,下一条记录存储到新索引位置
        }
    } while (s);

    // 输出所有有效记录
    for(int i = 0; i < count; i++){
        printf("name = %s; ", net_devices[i].name);
        printf("IPv4 = %s; ", net_devices[i].IPv4);
        printf("isOnline = %s; ", net_devices[i].isOnline);
        printf("\n");
    }

    // 正确释放内存:先释放每个元素的name字段,再释放数组本身
    for (int i = 0; i < count; i++) {
        free(net_devices[i].name);
    }
    free(net_devices);
    return 0;
}

关键逻辑说明

  • 用capacity记录数组总可用容量,count记录已存储的有效元素数,逻辑清晰易维护。
  • 每次拿到合法输入后先判断容量是否充足,不足时再执行扩容,完全符合每输入一条扩容一次的需求。
  • 存储完成后count自增,避免新数据覆盖旧记录。
  • 字符串拷贝使用strncpy强制补结束符,避免缓冲区溢出。
  • 释放内存时先遍历释放每个name字段的堆内存,再释放结构体数组,避免内存泄漏。

内容的提问来源于stack exchange,提问作者mobdevkun

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.24 16:06:07