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

如何为不同组创建独立内存地址的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;
    }
}

关键修改说明

  1. 解决内存泄漏:移除了原代码中st2的多余calloc操作,所有通过calloc分配的内存都能在clear函数中通过链表遍历逐一释放。
  2. 实现独立内存:每个ID对应一个全新的MySettings实例(calloc分配),且每个实例的block也单独分配内存,确保所有配置的内存地址完全独立。
  3. 处理重复组ID:将Settings改为链表数组,同一组的多个配置通过链表串联,避免了指针覆盖问题,同时保证所有配置都能被管理和释放。
  4. 简化逻辑:去掉了冗余的st2指针,直接操作当前ID对应的配置实例,代码更清晰。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.28 08:23:02