使用setjmp、longjmp创建无限循环触发段错误的问题咨询
问题根因定位
- 函数名拼写错误。C标准库中的跳转函数名是全小写的
longjmp,你代码中写的longJmp(J大写)、longjump(多了字母u)都属于非法函数名,未做宏定义替换的话会直接编译失败。 - 全局
jmp_buf被重复覆盖。全局变量buf1先后被main和foo中的setjmp调用写入,foo中的后一次setjmp直接覆盖了main中保存的上下文,最终buf1里仅保留foo函数的栈上下文信息。 longjmp传参与分支判断不匹配。根据你的补充说明,实际代码中调用的是longjmp(buf1, 2),但foo中仅处理了v==0和v==1的分支,当setjmp返回2时,两个分支都不命中,foo函数直接执行完毕返回main。- 访问已销毁的栈帧(触发段错误的直接原因)。
foo返回后其对应的栈帧已经被系统回收销毁,此时你调用main中foo后的longjmp(buf1,1),尝试跳转回已经不存在的foo栈帧中的setjmp位置,属于C标准明确规定的未定义行为,会直接触发栈越界访问,导致段错误。
修正方案
要实现你预期的C1A4B1B1B1……无限输出,只要保证longjmp参数匹配分支判断,且foo函数永远不会返回即可,修正后的参考代码如下:
#include <stdio.h> #include <setjmp.h> jmp_buf buf1; void foo(){ int z = 4, y = 1; int v = setjmp(buf1); if(v == 0){ printf("A%d", z); longjmp(buf1, 1); } else if(v == 1){ printf("B%d", y); longjmp(buf1, 1); } } int main(){ int v = setjmp(buf1); if( v == 0){ printf("C%d", 1); foo(); // 该行及后续代码永远不会被执行 } return 0; }
内容的提问来源于stack exchange,提问作者Asurii
相关产品推荐
相关产品推荐

