C程序出现RegisterSecureMemoryCacheCallback异常,free数组时崩溃求助
错误现象
程序在调用free(a)时触发崩溃,调试器输出错误信息:
Thread 1 received signal SIGTRAP, Trace/breakpoint trap.
0x00007ffd80a5719f in ntdll!RtlRegisterSecureMemoryCacheCallback () from C:\Windows\SYSTEM32\ntdll.dll
直接在main函数内使用malloc分配内存时程序运行正常,曾怀疑是函数作用域问题,但认为返回malloc指针后释放位置不应影响程序。
问题代码
#include <stdlib.h> #include <string.h> #include <stdio.h> typedef struct array { int length; int size; void *data; } array; static array* new(int length, int size) { array *array = malloc(sizeof(array)); array->length = length; array->size = size; array->data = malloc(length * size); return array; } int main() { array *a = new(5, sizeof(int)); free(a->data); free(a); // debugger points me to here return 0; }
根本原因
代码的核心问题是变量名与结构体类型名重名:
在new函数中,局部指针变量array的名字和结构体类型array完全一致。C语言中局部变量会屏蔽同名的全局类型名,导致sizeof(array)计算的是指针的大小(32位系统为4字节,64位系统为8字节),而非结构体array的实际大小(结构体包含两个int和一个void*,64位下为24字节)。
这使得malloc(sizeof(array))分配的内存远小于结构体所需空间,后续给array->length、array->size、array->data赋值时会越界写入堆内存,破坏堆的内部结构。当调用free(a)时,堆管理器检测到结构损坏,触发SIGTRAP错误。
修复方法
修改new函数中的局部变量名,避免与结构体类型名冲突,同时推荐用sizeof(*变量)的方式计算结构体大小,更安全且易于维护:
static array* new(int length, int size) { // 变量名改为arr,避免与类型名array冲突 array *arr = malloc(sizeof(*arr)); if (arr == NULL) { // 建议添加malloc失败的判断逻辑 return NULL; } arr->length = length; arr->size = size; arr->data = malloc(length * size); return arr; }
sizeof(*arr)会直接计算出结构体array的实际大小,即便后续结构体定义修改,也能保证分配足够的内存,避免越界问题。
内容的提问来源于stack exchange,提问作者user2980746

