这篇文章主要讲解了“setjmp的使用方法”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“setjmp的使用方法”吧!
以前对于C语言的setjmp和longjmp从来都是知道有这么个函数, 但是不知道什么情况下要使用, 甚至于不知道setjmp的实现机制是什么样子的.
这次在<a href="https://github.com/findstr/coroutine" title="实现coroutine的过程中">实现coroutine的过程中</a>虽然没有使用setjmp来实现, 但是由于setjmp来实现coroutine的所有操作都是可以在用户态进行的, 因此顺便研究了一下<a href="http://www.jbox.dk/sanos/source/lib/setjmp.c.html" title="setjmp的实现机制">setjmp的实现机制</a>.
与我猜测大致一样, 在call stack上来讲setjmp一定先于或等于longjmp处于的位置, 这样其实longjmp所做的不过就是将当前寄存器上下文恢复成setjmp函数保存的值即可. 调用longjmp的函数与调用setjmp的函数共用一个栈空间, 因此longjmp恢复完寄存器后造成的结果就是恢复寄存器上下文并将栈空间释放到setjmp位于的地方.
那么这就很好解释为什么不能将setjmp使用函数再封装一层了, 假设使用函数封装setjmp代码如下:
<code>
int try(jmp_buf jmp)
{
int err;
err = setjmp(jmp);
printf("%d\n", err);
return err;
}
void execption(jmp_buff j, int err)
{
return longjmp(j, err)
}
int main()
{
jmp_buff j;
try(j);
execption(j, 2);
}
</code>
如上代码其实try函数与execption共用部分栈空间, 当longjmp回到try函数时, 即使用寄存器被恢复了, 但是事实上try函数的栈结构已经被破坏了, 此时longjmp之后try函数的行为是无法预料的.
<pre>
------------------------
| main |
|-----------------------
| try | excption |
|---------| |
|---------|------------|
</pre>
在使用setjmp时一定要注意栈是否被覆盖的问题, 即调用setjmp时所保存的esp的信息直到调用前longjmp之前, 不应该会出更有比setjmp保存esp时更多的空闲空间(如栈是自顶向下增加, 则setjmp到longjmp之间出现的esp的值绝不能大于setjmp保存的esp的值.
感谢各位的阅读,以上就是“setjmp的使用方法”的内容了,经过本文的学习后,相信大家对setjmp的使用方法这一问题有了更深刻的体会,具体使用情况还需要大家实践验证。这里是亿速云,小编将为大家推送更多相关知识点的文章,欢迎关注!
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。