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

如何修复aligned_alloc中指针解引用引发的C语言内存访问违例?

修复aligned_alloc中的内存访问违例错误

我在用Tbman(快速易用的内存管理器)实现内存管理器,需要适配aligned_alloc方法。修改了网上找到的代码后,运行Tbman测试时在*((unsigned char*)(ret - 1)) = offset;行抛出异常:Exception thrown 0xC0000005: Access violation writing location 0xFFFFFFFF87FA06FF。

修改后的代码

void *aligned_alloc(size_t alignment, size_t size)
{
    size_t n = size + alignment - sizeof(void*);
    bool zero = false;
    char* p = (char*)(zero ? calloc(1, n) : malloc(sizeof(void*) + n));

    if (p)
    {
        size_t remainder = ((size_t)p) % alignment;
        size_t offset = alignment - remainder;
        char* ret = p + (unsigned char)offset;

        // store how many extra bytes we allocated in the byte just before the pointer we return
        *((unsigned char*)(ret - 1)) = offset;

        return (void*)ret;
    }

    return NULL;
}

网上原始代码

void *aligned_alloc(size_t alignment, size_t size, bool zero) {
    size_t request_size = size + alignment;
    char* buf = (char*)(zero ? calloc(1, request_size) : malloc(request_size));

    size_t remainder = ((size_t)buf) % alignment;
    size_t offset = alignment - remainder;
    char* ret = buf + (unsigned char)offset;

    // store how many extra bytes we allocated in the byte just before the
    // pointer we return
    *(unsigned char*)(ret - 1) = offset;

    return (void*)ret;
}

问题核心原因

  1. 偏移量截断导致越界:用unsigned char强制转换offset时,若alignment > 255且原指针已对齐,offset = alignment会被截断为0,导致ret = p,此时ret-1指向p的前一个未分配内存字节,触发访问违例。
  2. 存储空间不足:仅用1字节存储offset,无法容纳大于255的偏移量,后续释放内存也会出错。
  3. 未预留偏移存储区:没有为偏移量单独预留内存空间,存在越界访问风险。

修复后的代码

#include <stddef.h>
#include <stdlib.h>

void *aligned_alloc(size_t alignment, size_t size)
{
    // 符合标准要求:alignment必须是2的幂,size不能为0
    if (size == 0 || (alignment & (alignment - 1)) != 0) {
        return NULL;
    }

    // 分配总空间:实际数据大小 + 最大对齐偏移 + 偏移量存储区
    size_t total_size = size + alignment + sizeof(size_t);
    bool zero = false;
    char *p = (char *)(zero ? calloc(1, total_size) : malloc(total_size));

    if (p == NULL) {
        return NULL;
    }

    // 从偏移存储区之后开始计算对齐地址
    size_t base_addr = (size_t)(p + sizeof(size_t));
    size_t remainder = base_addr % alignment;
    size_t offset = remainder == 0 ? 0 : alignment - remainder;
    char *ret = p + sizeof(size_t) + offset;

    // 将总偏移量(存储区+对齐偏移)写入预留空间
    *(size_t *)(ret - sizeof(size_t)) = sizeof(size_t) + offset;

    return ret;
}

// 配套的内存释放函数
void aligned_free(void *ptr)
{
    if (ptr == NULL) {
        return;
    }
    size_t offset = *(size_t *)((char *)ptr - sizeof(size_t));
    free((char *)ptr - offset);
}

修复点说明

  1. 输入合法性校验:添加对alignment是否为2的幂、size是否为0的检查,符合标准aligned_alloc的行为规范。
  2. 内存空间预留:额外分配sizeof(size_t)的空间存储偏移量,确保写入操作在分配的内存范围内,避免越界。
  3. 对齐地址计算优化:从偏移存储区之后开始计算对齐地址,彻底避免ret指向原指针导致的越界问题。
  4. 偏移量安全存储:用size_t类型存储偏移量,支持大数值偏移,不会出现截断;存储的偏移量包含预留的存储区大小,方便后续释放时定位原始指针。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.13 17:30:52