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

C语言内存块分配时主块被覆盖的问题及修正方案咨询

解决C语言内存块管理与持久化的问题

核心问题分析

你的问题出在内存块数组的更新逻辑错误——分配进程内存时,直接覆盖了主块的内存空间,而没有正确扩容数组来新增进程块,同时主块的大小调整也未按预期执行。

修正步骤与代码示例

1. 定义内存块结构体

明确区分主可用块和进程分配块的结构:

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

typedef struct {
    // 0=主可用块,1=进程分配块
    int type;
    // 块大小(字节)
    size_t size;
    // 进程ID(仅进程块有效)
    int pid;
} MemoryBlock;

2. 从文件加载内存块状态

启动时读取block.dat,文件不存在则初始化主块:

MemoryBlock* load_blocks(size_t *count) {
    FILE *fp = fopen("block.dat", "rb");
    MemoryBlock *blocks = NULL;
    *count = 0;

    if (fp) {
        // 先读取块总数
        fread(count, sizeof(size_t), 1, fp);
        // 分配内存加载所有块数据
        blocks = malloc(*count * sizeof(MemoryBlock));
        fread(blocks, sizeof(MemoryBlock), *count, fp);
        fclose(fp);
    } else {
        // 初始化总可用内存为1024KB
        *count = 1;
        blocks = malloc(sizeof(MemoryBlock));
        blocks[0].type = 0;
        blocks[0].size = 1024 * 1024;
        blocks[0].pid = -1;
    }
    return blocks;
}

3. 正确实现内存分配逻辑

核心逻辑:找到主可用块→检查空间→扩容数组新增进程块→调整主块大小(或移除空主块)

int allocate_memory(MemoryBlock **blocks, size_t *count, int pid, size_t alloc_size) {
    // 定位主可用块
    int main_idx = -1;
    for (size_t i = 0; i < *count; i++) {
        if ((*blocks)[i].type == 0) {
            main_idx = i;
            break;
        }
    }
    if (main_idx == -1 || (*blocks)[main_idx].size < alloc_size) {
        printf("内存不足,分配失败\n");
        return -1;
    }

    // 扩容内存块数组,新增进程块
    *blocks = realloc(*blocks, (*count + 1) * sizeof(MemoryBlock));
    if (!*blocks) {
        printf("动态内存分配失败\n");
        return -1;
    }

    // 写入新进程块数据
    (*blocks)[*count].type = 1;
    (*blocks)[*count].size = alloc_size;
    (*blocks)[*count].pid = pid;
    (*count)++;

    // 调整主块大小
    MemoryBlock *main_block = &(*blocks)[main_idx];
    main_block->size -= alloc_size;
    // 主块空间耗尽则移除
    if (main_block->size == 0) {
        memmove(main_block, main_block + 1, (*count - main_idx - 1) * sizeof(MemoryBlock));
        (*count)--;
        // 可选:缩小数组避免内存浪费
        *blocks = realloc(*blocks, (*count) * sizeof(MemoryBlock));
    }

    return 0;
}

4. 持久化内存块状态到文件

每次分配后,将块总数和所有块数据写入block.dat:

void save_blocks(MemoryBlock *blocks, size_t count) {
    FILE *fp = fopen("block.dat", "wb");
    if (!fp) {
        printf("保存内存块状态失败\n");
        return;
    }
    // 先写入块总数,再写入块数据
    fwrite(&count, sizeof(size_t), 1, fp);
    fwrite(blocks, sizeof(MemoryBlock), count, fp);
    fclose(fp);
}

5. 测试示例

int main() {
    size_t block_count;
    MemoryBlock *blocks = load_blocks(&block_count);

    // 给进程1分配256KB
    allocate_memory(&blocks, &block_count, 1, 256*1024);
    // 给进程2分配512KB
    allocate_memory(&blocks, &block_count, 2, 512*1024);

    // 打印当前内存块状态
    printf("当前内存块状态:\n");
    for (size_t i = 0; i < block_count; i++) {
        if (blocks[i].type == 0) {
            printf("主可用块:%zuKB\n", blocks[i].size / 1024);
        } else {
            printf("进程%d:%zuKB\n", blocks[i].pid, blocks[i].size / 1024);
        }
    }

    save_blocks(blocks, block_count);
    free(blocks);
    return 0;
}

关键注意事项

  • 操作内存块数组时,必须用realloc扩容/缩容,禁止直接覆盖原有元素
  • 主块空间耗尽后要及时移除,避免无效数据残留
  • 持久化时先写块总数再写块数据,保证加载时能正确解析
  • 所有动态分配的内存要在程序结束前释放,避免内存泄漏

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.17 14:01:11