longjmp 为什么进入死循环??

微信公众号 2013-03-06 03:51:33
#include <stdio.h>
#include <stdlib.h>
#include <setjmp.h>

void test();

jmp_buf buf1,buf2;

int main(void)
{
if(setjmp(buf1))
{
printf("longjmp back main.\n");
longjmp(buf2,2);
}
else {
printf("first go here.\n");
test();
}
exit(0);
}

void test()
{
static int m=10;
printf("test function.\n");
m+=20;
if(setjmp(buf2)==0)
longjmp(buf1,1);
printf("m:%d",m);
}


代码如上所示,程序为什么进入死循环了呢?
测试运行结果:
一直死循环了……
...全文
275 12 打赏 收藏 转发到动态 举报
写回复
用AI写文章
12 条回复
切换为时间正序
请发表友善的回复…
发表回复
赵4老师 2013-03-07
  • 打赏
  • 举报
回复
对学习编程者的忠告: 眼过千遍不如手过一遍! 书看千行不如手敲一行! 手敲千行不如单步一行! 单步源代码千行不如单步对应汇编一行!
raison_x 2013-03-06
  • 打赏
  • 举报
回复
1. 在 Linux 下面setjmp & longjmp 的现场保存和恢复做的比较好,保存了所有寄存器和调用setjmp时的堆栈的值。你的buf1 保存了main()的寄存器和堆栈,buf2保存了test()的寄存器和堆栈。你那交叉调用longjmp就导致了交叉恢复,倒腾来倒腾去了。我在CentOS 5.8里面测试,它连 m 的值都是递增20 。。。 2. 不建议交叉调用,这会让你的程序的逻辑像乱麻,本身setjmp & longjmp 都已经是非不得已不采用的东西,因为它会潜在改变运行逻辑。 3. 不同的系统对其的支持不同。
majia2011 2013-03-06
  • 打赏
  • 举报
回复
看汇编没用的,你要单步调试在,在test的ret,看栈,看跳转
微信公众号 2013-03-06
  • 打赏
  • 举报
回复
上面是汇编代码,自己看不太懂,只懂一点x86的。my_live_123的回复看明白了,只是不明白Linux下是如何处理的?
微信公众号 2013-03-06
  • 打赏
  • 举报
回复
    .file    "test3.c"
    .comm    buf1,156,32
    .comm    buf2,156,32
    .section    .rodata
.LC0:
    .string    "first go here."
    .text
.globl main
    .type    main, @function
main:
    pushl    %ebp
    movl    %esp, %ebp
    andl    $-16, %esp
    subl    $16, %esp
    movl    $buf1, (%esp)
    call    _setjmp
    testl    %eax, %eax
    je    .L2
    movl    $2, 4(%esp)
    movl    $buf2, (%esp)
    call    longjmp
.L2:
    movl    $.LC0, (%esp)
    call    puts
    call    test
    movl    $0, (%esp)
    call    exit
    .size    main, .-main
    .section    .rodata
.LC1:
    .string    "test function."
.LC2:
    .string    "m:%d"
    .text
.globl test
    .type    test, @function
test:
    pushl    %ebp
    movl    %esp, %ebp
    subl    $24, %esp
    movl    $.LC1, (%esp)
    call    puts
    movl    m.2223, %eax
    addl    $20, %eax
    movl    %eax, m.2223
    movl    $buf2, (%esp)
    call    _setjmp
    testl    %eax, %eax
    jne    .L5
    movl    $1, 4(%esp)
    movl    $buf1, (%esp)
    call    longjmp
.L5:
    movl    m.2223, %edx
    movl    $.LC2, %eax
    movl    %edx, 4(%esp)
    movl    %eax, (%esp)
    call    printf
    leave
    ret
    .size    test, .-test
    .data
    .align 4
    .type    m.2223, @object
    .size    m.2223, 4
m.2223:
    .long    10
    .ident    "GCC: (GNU) 4.4.4 20100726 (Red Hat 4.4.4-13)"
    .section    .note.GNU-stack,"",@progbits
一根烂笔头 2013-03-06
  • 打赏
  • 举报
回复
我用的vc6.0跑你的程序未出现死循环,倒是出现了越界问题,然后找到了错误

#include <stdio.h>
#include <stdlib.h>
#include <setjmp.h>
 void test();
 jmp_buf buf1,buf2;

 void main(void)
 {    
	 if(setjmp(buf1))//setjmp返回0执行test;(2)-值为1,成立
	 {        
		 printf("longjmp back main.\n");
		 longjmp(buf2,2);//调回buf2时,原来的test调用保存的栈内容已经消亡,再进行函数跳出时候出现错误《——错误就在这里

	 }
	 else {
		 printf("first go here.\n");
		 test();
	 }
	 //exit(0);
 } 
 void test()
 {
	int m=10;
	 printf("test function.\n");
    m+=20;
    if(setjmp(buf2)==0)//成立
        longjmp(buf1,1);//调回buf1处,值为1,到(2),注意在这里test调用也就算结束了
    printf("m:%d",m);//把static去掉后,你会看到结果不是10也不是30是个随机值,也就说明不是继续上次test调用后执行
} 
 
ForestDB 2013-03-06
  • 打赏
  • 举报
回复
NB
majia2011 2013-03-06
  • 打赏
  • 举报
回复
好大的一个goto,单步调试一下吧,呵呵呵
金刚葫芦娃 2013-03-06
  • 打赏
  • 举报
回复
longjmp(buf2,2); longjmp(buf1,1); 这俩来回跳呢.
七擒关羽 2013-03-06
  • 打赏
  • 举报
回复
你一直在2个缓存 中跳转,当然死循环了
赵4老师 2013-03-06
  • 打赏
  • 举报
回复
仅供参考
#include <stdio.h>
#include <setjmp.h>
jmp_buf mark;
int i=0;
void c() {
    printf( "c in\n");
    if (1==i%2) longjmp( mark, i );
    printf( "c out\n");
}
void b() {
    printf( "b in\n");
    c();
    printf( "b out\n");
}
void a() {
    printf( "a in\n");
    b();
    printf( "a out\n");
}
void main( void )
{
   int jmpret;
   jmpret = setjmp( mark );
   printf( "Start %d\n",jmpret);
   if( jmpret == 0 ) {
       printf( "First\n");
       a();
       i++;
       a();
   } else {
       printf( "Second\n");
   }
}
//Start 0
//First
//a in
//b in
//c in
//c out
//b out
//a out
//a in
//b in
//c in
//Start 1
//Second
//
金刚葫芦娃 2013-03-06
  • 打赏
  • 举报
回复
mark一下,查阅下文档,没接触过longjmp.

69,371

社区成员

发帖
与我相关
我的任务
社区描述
C语言相关问题讨论
社区管理员
  • C语言
  • 花神庙码农
  • 架构师李肯
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧