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

C语言malloc分配内存后越界访问部分正常部分崩溃原因

现象本质原因

你遇到的所有现象,核心根源是两个:

  • C语言完全没有内置的内存越界检查机制,和Python访问列表会自动校验下标范围、越界直接抛IndexError不同,C编译器和CPU默认不会判断你访问的内存位置是不是你之前申请过的。只要访问的地址是进程拥有读写权限的合法地址,读写操作本身就会正常执行,不会立刻报错。
  • 你用的Linux系统默认的malloc实现(glibc里的ptmalloc)自己维护堆内存的元数据,只有当越界写破坏了这些元数据、被malloc的自检逻辑抓到的时候,才会主动终止程序报错。

为什么越界访问arr[2]~arr[5]时程序"正常运行"

你申请2*sizeof(int)时,64位系统下实际申请的用户可用内存是8字节,但ptmalloc分配内存时不会严格按照你申请的字节数精准切割:

  • 首先所有内存分配都会按固定粒度对齐(64位系统下一般按16字节对齐),其次每个堆块在返回给用户的指针前面,自带16字节的堆块元数据(存块大小、是否空闲等信息)。
  • 你申请8字节内存时,实际给你划分的用户可写区域远大于8字节,块后面紧挨着的是堆顶未分配的空闲内存(叫top chunk),这部分内存本身属于进程的可读写堆段,CPU允许读写。

你给arr[2]到arr[5]赋值时,写入的位置要么在分配块的对齐冗余空间里,要么在top chunk的空闲数据区域,没有碰到关键的元数据,程序运行过程中也没有再调用malloc/free触发堆一致性检查,所以会"看起来正常运行"。

注意:这是未定义行为,绝对不代表代码是合法的。如果后续这部分内存被malloc分配给其他变量,你之前写入的值会篡改其他变量的内容,引发极难排查的偶发bug——这类bug可能在你写代码几小时甚至几天后才会暴露,没有固定复现规律。


为什么写arr[6]就会崩溃报malloc(): corrupted top size

你看到的报错不是操作系统触发的段错误,是ptmalloc的自检逻辑主动抛出的:
top chunk作为堆顶的空闲块,在它的起始位置存了自己的元数据,其中就包括top chunk的大小字段。当你给arr[6]赋值时,写入的偏移量是6*4=24字节,刚好覆盖了top chunk的size字段,把原本合法的大小值改成了你写入的777777777——这个值不符合内存对齐要求,属于非法值。
当main函数执行结束、C运行时做堆内存清理时,会检查堆结构的完整性,发现top chunk的size被破坏,就会主动调用abort终止程序,输出你看到的错误信息。
你把malloc分配大小改成3*sizeof(int)(12字节)时,arr[6]的偏移位置依然刚好落在top chunk的元数据区,所以还是会触发同样的报错。


关键认知纠正
  • 不要把"程序没崩溃"等同于"代码写对了":C语言的未定义行为没有任何确定性后果,可能正常输出、可能出随机错值、可能当场崩溃,没有任何规律可言。
  • 内存访问权限是按页管理的(通常每页4KB):只要你访问的地址在当前进程已申请的、有读写权限的内存页内,CPU根本不会管你有没有调用malloc申请过这块地址,只有访问了未映射的地址、或者只读地址时,才会立刻触发硬件级别的段错误。
  • 你看到的堆损坏报错是glibc的保护机制:换到没有堆自检的运行时环境(比如部分嵌入式系统),哪怕越界写几十上百字节,程序也可能不会立刻崩溃,直到出现完全无法溯源的逻辑错误。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.30 23:00:57