C语言编写四则运算程序触发SIGSEGV段错误原因排查
C语言四则运算程序段错误根因及修复
核心触发原因
段错误的直接诱因是scanf函数传参错误,所有scanf调用均未传入变量的内存地址,而是直接传入未初始化的变量本身。scanf的工作机制是将用户输入的值写入参数指定的内存地址,未初始化的局部变量存储的是随机垃圾值,scanf会把这个随机值当作目标内存地址尝试写入,触发非法内存访问,最终抛出SIGSEGV段错误。
具体代码疏漏
- 三处
scanf调用全部遗漏取地址运算符&:
原错误写法:
正确写法需要给每个传入的变量前加scanf("%d", vIn_a); scanf("%d", vIn_b); scanf("%c", vOperator);&,传递变量地址。 - 输入逻辑存在缓冲区残留问题:输入第二个整数后按下的回车换行符会残留在标准输入缓冲区,会被第三个读取字符的
scanf直接捕获,导致程序不会等待用户输入运算符,直接读取到换行符,后续switch分支无法匹配,运算结果变量为未初始化的随机值。 - 缺少非法输入、除零错误的兜底判断,鲁棒性不足。
gdb报错说明
Program received signal SIGSEGV, Segmentation fault.
0x00007ffff7c60d36 in ?? () from /usr/lib/libc.so.6
该报错指向C标准动态库libc.so.6是因为段错误实际触发在scanf的库函数实现逻辑中,系统未加载libc的调试符号因此显示??,并非标准库本身存在故障,根因是传入的非法参数。
修复后完整代码
#include <stdio.h> int main () { int vIn_a, vIn_b, vIn_c; char vOperator; printf("Please enter a number\n"); scanf("%d", &vIn_a); printf("Please enter a number\n"); scanf("%d", &vIn_b); printf("Please enter a Operator\n"); // 格式串开头的空格用于跳过缓冲区中残留的换行、空格等空白字符 scanf(" %c", &vOperator); switch(vOperator){ case '+': vIn_c = vIn_a + vIn_b; break; case '-': vIn_c = vIn_a - vIn_b; break; case '/': // 增加除零判断避免运行时错误 if (vIn_b == 0) { printf("Error: division by zero\n"); return 1; } vIn_c = vIn_a / vIn_b; break; case '*': vIn_c = vIn_a * vIn_b; break; default: printf("Error: invalid operator\n"); return 1; } printf("Result: %d %c %d = %d\n", vIn_a, vOperator, vIn_b, vIn_c); return 0; }
内容的提问来源于stack exchange,提问作者PrebenL
相关产品推荐
相关产品推荐

