如何修复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; }
问题核心原因
- 偏移量截断导致越界:用
unsigned char强制转换offset时,若alignment > 255且原指针已对齐,offset = alignment会被截断为0,导致ret = p,此时ret-1指向p的前一个未分配内存字节,触发访问违例。 - 存储空间不足:仅用1字节存储
offset,无法容纳大于255的偏移量,后续释放内存也会出错。 - 未预留偏移存储区:没有为偏移量单独预留内存空间,存在越界访问风险。
修复后的代码
#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); }
修复点说明
- 输入合法性校验:添加对
alignment是否为2的幂、size是否为0的检查,符合标准aligned_alloc的行为规范。 - 内存空间预留:额外分配
sizeof(size_t)的空间存储偏移量,确保写入操作在分配的内存范围内,避免越界。 - 对齐地址计算优化:从偏移存储区之后开始计算对齐地址,彻底避免
ret指向原指针导致的越界问题。 - 偏移量安全存储:用
size_t类型存储偏移量,支持大数值偏移,不会出现截断;存储的偏移量包含预留的存储区大小,方便后续释放时定位原始指针。
内容的提问来源于stack exchange,提问作者dustin watson
相关产品推荐
相关产品推荐

