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

