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

C语言结构体初始化后int成员打印值异常排查

问题诊断

这是明确的内存分配错误引发的未定义行为,bug出在初始化函数的calloc调用上。
你的代码里Person是typedef定义的结构体指针类型,不是结构体本身:

typedef struct PERSON { ... } * Person;

在init_person中你写的分配逻辑是calloc(1, sizeof(Person)),这里sizeof(Person)计算的是指针的大小:64位系统下指针固定为8字节,32位系统下为4字节。但你实际需要存储的struct PERSON结构体大小远大于这个值:包含两个8字节的char指针、两个4字节的int,64位系统下总大小为24字节。
你只分配了8字节的堆内存,却要往里面存24字节的结构体内容,从surname成员开始的所有数据都写到了已分配内存块的边界外,属于堆缓冲区溢出。

  • 为什么交换printf顺序输出就看似正常?未定义行为的表现没有任何确定性:你越界写入的month、day值刚好落在堆上相邻的未使用区域,当先执行字符串打印的printf时,printf函数内部运行会临时使用这片相邻内存,把你之前写入的12、12覆盖成随机值,打印出来就是乱码一样的数字;如果先执行数字打印的printf,还没等其他逻辑覆盖那片越界内存,就能刚好读到你之前写入的正确值——这完全是巧合,代码随时可能触发崩溃、逻辑异常等问题。
修复方法

核心是修正内存分配的大小计算,两种正确写法任选其一即可:

  1. 最不容易出错的写法,以指针指向的实际类型计算大小,后续即使结构体定义修改也不会出问题:
Person person = calloc(1, sizeof(*person));
  1. 显式指定结构体类型计算大小:
Person person = calloc(1, sizeof(struct PERSON));

额外提示:直接把结构体指针typedef为不带指针标识的类型名(比如你写的Person)是C开发中很容易踩坑的写法,会让开发者很容易忽略这是个指针类型,在写sizeof、参数传递时很容易出现类似本次的大小计算错误,更稳妥的写法是typedef结构体本身,需要用指针的时候显式加*。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 06:22:04