最近在读 lua 5.1.5 源码
, 看到以下代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| #if defined(__cplusplus)
#define LUAI_THROW(L,c) throw(c) #define LUAI_TRY(L,c,a) try { a } catch(...) \ { if ((c)->status == 0) (c)->status = -1; } #define luai_jmpbuf int
#elif defined(LUA_USE_ULONGJMP)
#define LUAI_THROW(L,c) _longjmp((c)->b, 1) #define LUAI_TRY(L,c,a) if (_setjmp((c)->b) == 0) { a } #define luai_jmpbuf jmp_buf
#else
#define LUAI_THROW(L,c) longjmp((c)->b, 1) #define LUAI_TRY(L,c,a) if (setjmp((c)->b) == 0) { a } #define luai_jmpbuf jmp_buf
#endif
|
十分疑惑,所以就在网上找了资料学习了下。
怎么回事儿?
setjmp
和 longjmp
需要通过 jmp_buf
结合起来使用:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
| do { jmp_buf __buf;
* setting exceptions handling */ switch(setjmp(__buf)) { case 0 : break; case EXCEPTION_TYPE_1 : break; case EXCEPTION_TYPE_2 : break; case EXCEPTION_TYPE_3 : break; . . . default : break; }
* there are some try blocks */ {
* throw a exception */ longjmp(__buf, EXCEPTION_TYPE_VALUE); }
} while(0);
|
setjmp
第一次执行的时候返回的是 0
,表示成功设置 jmp_buf
longjmp
每次执行之后,程序便会跳转到 setjmp
处,再去执行 setjmp
, 不过此时 setjmp
执行之后的返回值是本次 longjmp
调用时传入的第二个参数 EXCEPTION_TYPE_VALUE
setjmp
和 longjmp
需要使用同一个 jmp_buf
这里我就很无赖的直接贴上这篇文章([Exceptions in C with Longjmp and Setjmp])最后的给出的代码([try_throw_catch.h])以供参考
最后说点其他的
看到这对函数,我更加明白为何在异常处理中出现异常会很难处理了。也突然想起之前学C语言的时候,书上不建议使用 goto
来写程序。说不定 setjmp
和 longjmp
的实现和 goto
有点关系呢。
_setjmp 和 setjmp 区别
[_setjmp(3) - Linux man page]
- _longjmp, _setjmp - non-local goto
goto 和 setjmp, longjmp 区别
[Difference between goto and longjmp() and setjmp()]
goto
只能在单一函数中实现跳转
setjmp
, longjmp
可以实现在不同函数之间进行跳转