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

C程序出现RegisterSecureMemoryCacheCallback异常,free数组时崩溃求助

C程序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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.16 16:39:58