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

C语言:无前置printf调用时触发段错误问题排查

段错误根本原因定位

你遇到的是C语言开发里非常典型的未定义行为引发的偶发崩溃,核心bug出在内存分配的尺寸计算上,和printf语句本身没有任何关系。

问题复现代码

fscanf(input, "%d %d", &numofusers, &numofmovies);
//-----users list allocation
for (int i = 0; i < numofusers; i++) {
    curruser->usercode = i + 1;

    //without this 7th line I get a segmentation fault at line 15 (without line 15 program termines successfully)
    printf("%d %d %d\n\n", numofusers, numofmovies, curruser->usercode);
    //through this line of code I understood that it does what I want it to do

    curruser->next = calloc(1, sizeof(struct user *)); // 错误就在这一行
    curruser = curruser->next;
}
curruser = headuser;
//--------
printf("!%d!\n", numofmovies);

核心错误点

  • 内存分配尺寸传错:calloc第二个参数你写的是sizeof(struct user *),这个值计算的是指向user结构体的指针的内存大小(32位系统为4字节,64位系统为8字节),远小于struct user结构体本身实际需要的内存长度。

为什么加/删printf会影响崩溃表现

这种“加个打印就不崩、删了打印就出问题”是堆内存越界的典型特征:

  1. 你申请的内存块不够大,后续给curruser->usercode、curruser->next赋值的时候,本质是在写入超出申请范围的堆内存,属于非法越界写,从C语言标准来说这已经触发未定义行为,程序的运行结果没有任何保障。
  2. 保留循环内的printf时,printf函数运行过程中会申请临时栈空间、修改堆内存布局,刚好把你越界写入的那片内存区域覆盖成了可读写的合法空间,没有触发操作系统的内存保护机制,所以看起来运行正常。
  3. 删掉循环内的printf后,内存布局发生变化,你越界写入的内容刚好踩坏了堆内存元数据,甚至覆盖了numofmovies变量所在的内存位置,等到执行最后一行printf读取numofmovies时,就触发了段错误。
  4. 如果连最后一行printf也删掉,程序没有再访问被踩坏的内存区域,跑完直接退出,就会出现“程序正常终止”的假象,但内存越界的问题始终存在,后续只要内存布局稍微变化就会崩溃。

修复方案

将错误的calloc调用修正,传入结构体本身的尺寸而非结构体指针的尺寸:

curruser->next = calloc(1, sizeof(struct user));

另外需要额外确认:进入for循环之前,headuser和初始的curruser指针已经完成了合法的内存分配、不是野指针,否则第一次循环给curruser->usercode赋值时同样会触发内存错误。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 18:12:12