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
相关产品推荐
相关产品推荐

