如何为不同组创建独立内存地址的MySettings实例(保留calloc)
问题分析与修改方案
原代码核心问题
- 内存泄漏:
st2通过calloc分配内存后,立刻执行st2 = st;,直接覆盖了calloc返回的地址,导致这块内存永远无法释放。 - 同组指针重复:
st2 = st;是指针赋值,并非创建新的配置副本。如果GetGroupID(i)返回相同的组ID,Settings[st->group]会被后续的指针覆盖,既丢失了之前的配置内存,又导致同一组最终只指向最后一个生成的配置地址。 - Block内存未独立:
count_block是read_db内的全局变量,每次循环递增,导致所有MySettings实例的block指针指向同一块不断扩容的内存,违背了“每个ID配置对应独立内存”的需求。
修改后的代码实现
#include <stdbool.h> #include <stdlib.h> struct Block { int id; }; struct MySettings { int conf_id; int group; int enable; bool hide_name; bool login_persistence; bool remove_cache; struct Block *block; // 新增链表节点,用于存储同一组的多个配置 struct MySettings *next; }; // 每个组用链表存储多个配置,避免覆盖 struct MySettings *Settings[50] = {NULL}; // 模拟GetGroupID函数(示例返回i%5生成重复组) int GetGroupID(int i) { return i % 5; } void read_db(void) { // 先清空旧数据,防止内存泄漏 clear(); for(int i = 0; i < 10; i++) { // 为当前ID创建独立的配置实例 struct MySettings *st = (struct MySettings*)calloc(1, sizeof(struct MySettings)); if (!st) continue; // 填充通用配置参数 st->conf_id = i; st->hide_name = true; st->login_persistence = true; st->remove_cache = true; st->enable = true; st->group = GetGroupID(i); st->next = NULL; // 为当前配置分配独立的Block内存 st->block = (struct Block*)calloc(1, sizeof(struct Block)); if (!st->block) { free(st); continue; } st->block->id = i + 1; // 将配置添加到对应组的链表中 if (!Settings[st->group]) { // 组内无配置,直接作为头节点 Settings[st->group] = st; } else { // 组内已有配置,追加到链表尾部 struct MySettings* temp = Settings[st->group]; while (temp->next) { temp = temp->next; } temp->next = st; } } } void clear(void) { for(int i = 0; i < 50; i++) { struct MySettings* current = Settings[i]; // 遍历链表释放所有配置实例 while (current) { struct MySettings* next_node = current->next; // 先释放Block内存 if (current->block) { free(current->block); } // 再释放配置实例 free(current); current = next_node; } Settings[i] = NULL; } }
关键修改说明
- 解决内存泄漏:移除了原代码中
st2的多余calloc操作,所有通过calloc分配的内存都能在clear函数中通过链表遍历逐一释放。 - 实现独立内存:每个ID对应一个全新的
MySettings实例(calloc分配),且每个实例的block也单独分配内存,确保所有配置的内存地址完全独立。 - 处理重复组ID:将
Settings改为链表数组,同一组的多个配置通过链表串联,避免了指针覆盖问题,同时保证所有配置都能被管理和释放。 - 简化逻辑:去掉了冗余的
st2指针,直接操作当前ID对应的配置实例,代码更清晰。
内容的提问来源于stack exchange,提问作者Michael
相关产品推荐
相关产品推荐

