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

遗留MUD代码free_mem函数魔数校验疑问及内存回收报错排查

MUD内存管理器报错与校验机制解析

问题背景

我正在维护一个遗留MUD代码库,运行时触发如下报错:

Attempt to recycle invalid memory of size 24.

对应内存释放函数代码如下,我有两个疑问:

  1. 该代码如何确保pMem指向的内存值始终为MAGIC_NUM?
  2. 内存地址不是随机的吗,这种校验机制为何能正常工作?
/*
 * Give a GP block back to the memory manager for recycling.
 */
void free_mem(void *pMem, size_t sMem) {
    int iList;

#ifdef MAGIC_CHECKING
    int *magic;

    pMem = (void *)(((char *)pMem) - sizeof(*magic));
    magic = (int *)pMem;

#ifndef MAGIC_NUM
#define MAGIC_NUM 52571214
#endif
    if (*magic != MAGIC_NUM) {
        bug("Attempt to recyle invalid memory of size %d.", sMem);
        bug((char *)pMem + sizeof(*magic), 0);
        return;
    }

    *magic = 0;
    sMem += sizeof(*magic);
#endif

    for (iList = 0; iList < MAX_MEM_LIST; iList++)
        if (sMem <= rgSizeList[iList])
            break;

    if (iList == MAX_MEM_LIST) {
        bug("Free_mem: size %d too large.", sMem);
        exit(EXIT_FAILURE);
    }

    *((void **)pMem) = rgFreeList[iList];
    rgFreeList[iList] = pMem;

    return;
}

解答

1. 如何保证校验位始终为MAGIC_NUM?

这个校验逻辑完全依赖配套内存分配函数(比如alloc_mem)的实现:

  • 当用户申请sMem大小的内存时,分配器实际会申请sMem + sizeof(int)的内存块
  • 在内存块的起始位置(也就是用户最终拿到的指针往前偏移sizeof(int)的位置)写入MAGIC_NUM
  • 最后返回给用户的指针是「内存块起始地址 + sizeof(int)」,相当于跳过了这个校验位

free_mem里的pMem = (void *)(((char *)pMem) - sizeof(*magic));就是把用户传入的指针往回偏移,找到这个预存的校验位。只有通过这套分配器申请的内存,才会在这个固定位置有MAGIC_NUM,以此确保要释放的是合法内存块。

2. 内存地址随机为何不影响校验?

内存地址随机(ASLR)是指程序虚拟地址空间的起始地址随机化,但这个校验机制和绝对地址无关:

  • 校验位的位置是相对于用户传入指针的固定偏移(往前一个int长度),不管整个内存块的绝对地址在哪,这个相对位置永远固定
  • 校验时只需要检查这个相对位置的值,和内存块的绝对地址没有关系,所以地址随机化不会干扰校验逻辑

报错的常见原因

出现这个错误通常是以下情况之一:

  • 传入了非本内存管理器分配的指针(比如用标准库malloc分配的内存,却调用free_mem释放)
  • 内存块被重复释放:第一次释放时,代码会把校验位设为0(*magic = 0;),第二次释放时就会触发校验失败
  • 内存越界写入:用户拿到内存指针后,往指针前面的区域写数据,破坏了预存的MAGIC_NUM
  • 使用了野指针:传入的指针指向已经被回收或从未分配的内存区域

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.18 06:28:15