当前时区为 UTC + 8 小时



发表新帖 回复这个主题  [ 3 篇帖子 ] 
作者 内容
1 楼 
 文章标题 : [C语言] 关于jmp_buf类型分析
帖子发表于 : 2017-04-20 21:20 

注册: 2014-10-28 14:53
帖子: 60
系统: ubuntu-14.04-LST
送出感谢: 1
接收感谢: 0 次
我在一个c语言实现的minigc源码(https://github.com/authorNari/minigc)的阅读中遇到一个问题。
关于编译jmp_buf类型变量,我已经查过了jmp_buf的含义,并且在google、wiki和stack overflow查询过相关问题没有结果。
疑惑代码如下,gc.c文件内的
代码:
static void
gc_mark_register(void)
{
    jmp_buf env;
    size_t i;
   
    /*
     * 把当前栈的上下文存储到env里
     * 保存env的时候成功返回0
     * 以后可以通过调用longjmp(env, vlu);
     * 返回到最后一次注册到env里的setjmp出,并且此时setjmp返回vlu
     * jmp_buf 本质是一个类数组类型!
     */
    setjmp(env);
    /* TODO 为何会对jmp_buf进行这种hark的操作? */
    for (i = 0; i < sizeof(env); i++) {
        gc_mark(((void **)env)[i]);
    }
}

问题是我们遍历env变量能的得到什么信息呢?


页首
 用户资料  
 
2 楼 
 文章标题 : Re: [C语言] 关于jmp_buf类型分析
帖子发表于 : 2017-07-27 20:14 
头像

注册: 2008-09-18 13:11
帖子: 2769
送出感谢: 1
接收感谢: 449
你直接看setjmp.h不就完了么
相关的定义如下:
代码:
# if __WORDSIZE == 64
typedef long int __jmp_buf[8];
# elif defined  __x86_64__
__extension__ typedef long long int __jmp_buf[8];
# else
typedef int __jmp_buf[6];
# endif

/* Calling environment, plus possibly a saved signal mask.  */
struct __jmp_buf_tag
  {
    /* NOTE: The machine-dependent definitions of `__sigsetjmp'
       assume that a `jmp_buf' begins with a `__jmp_buf' and that
       `__mask_was_saved' follows it.  Do not move these members
       or add others before it.  */
    __jmp_buf __jmpbuf;     /* Calling environment.  */
    int __mask_was_saved;   /* Saved the signal mask?  */
    __sigset_t __saved_mask;    /* Saved signal mask.  */
  };

typedef struct __jmp_buf_tag jmp_buf[1];

你要理解它是在干什么,就需要一点汇编语言和操作系统相关的知识。上面代码中提到的Calling environment,实际上就是指的是CPU的寄存器的值,你看这个函数的名称gc_mark_register,就是在标记寄存器。

一个最简化的程序
代码:
#include <setjmp.h>
int main(int argc,char **argv) {
   jmp_buf env;
   setjmp(env);
   return 0;
}

用gdb调试的结果,你可以自己看看env中包含的值与cpu寄存器的关系
代码:
(gdb) break main
Breakpoint 1 at 0x738: file a.c, line 2.
(gdb) r
Starting program: /tmp/a.out

Breakpoint 1, main (argc=1, argv=0x7fffffffdf78) at a.c:2
2   int main(int argc,char **argv) {
(gdb) s
4      setjmp(env);
(gdb) s
5      return 0;
(gdb) print env
$1 = {{__jmpbuf = {0, 5569584266273830259, 4294968816, 140737488346992, 0, 0, 5569584266370299251, -5569021317323737741},
    __mask_was_saved = 0, __saved_mask = {__val = {0, 0, 0, 0, 5658608, 194, 140737488346735, 140737488346734, 140737348619248, 1,
        4294969293, 0, 0, 4294969216, 4294968816, 140737488346992}}}}
(gdb) info registers
rax            0x0   0
rbx            0x0   0
rcx            0x0   0
rdx            0x4d4b23619f9b3573   5569584266370299251
rsi            0x0   0
rdi            0x7fffffffddc0   140737488346560
rbp            0x7fffffffde90   0x7fffffffde90
rsp            0x7fffffffddb0   0x7fffffffddb0
r8             0x1000007f0   4294969328
r9             0x7ffff7de7f90   140737351942032
r10            0x2   2
r11            0x1   1
r12            0x1000005f0   4294968816
r13            0x7fffffffdf70   140737488346992
r14            0x0   0
r15            0x0   0
rip            0x100000756   0x100000756 <main+54>
eflags         0x246   [ PF ZF IF ]
cs             0x33   51
ss             0x2b   43
ds             0x0   0
es             0x0   0
fs             0x0   0
gs             0x0   0
(gdb)


页首
 用户资料  
 
3 楼 
 文章标题 : Re: [C语言] 关于jmp_buf类型分析
帖子发表于 : 2017-07-27 21:47 

注册: 2014-10-28 14:53
帖子: 60
系统: ubuntu-14.04-LST
送出感谢: 1
接收感谢: 0 次
谢谢,这个问题在问了之后没多久我通过其他渠道弄懂了。这里没有关闭它,谢谢您的回答。我再熟悉下。


页首
 用户资料  
 
显示帖子 :  排序  
发表新帖 回复这个主题  [ 3 篇帖子 ] 

当前时区为 UTC + 8 小时


在线用户

正在浏览此版面的用户:没有注册用户 和 1 位游客


不能 在这个版面发表主题
不能 在这个版面回复主题
不能 在这个版面编辑帖子
不能 在这个版面删除帖子
不能 在这个版面提交附件

前往 :  
本站点为公益性站点,用于推广开源自由软件,由 DiaHosting VPSBudgetVM VPS 提供服务。
我们认为:软件应可免费取得,软件工具在各种语言环境下皆可使用,且不会有任何功能上的差异;
人们应有定制和修改软件的自由,且方式不受限制,只要他们自认为合适。

Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group
简体中文语系由 王笑宇 翻译