Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/71.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 我们是否可以将sigsetjmp重置为返回;0“;再次(重置sigsetjmp)?_C_Linux_Signals_Setjmp - Fatal编程技术网

C 我们是否可以将sigsetjmp重置为返回;0“;再次(重置sigsetjmp)?

C 我们是否可以将sigsetjmp重置为返回;0“;再次(重置sigsetjmp)?,c,linux,signals,setjmp,C,Linux,Signals,Setjmp,我使用sigsetjmp和siglongjmp编写了一个分段错误处理程序。一旦它进入信号处理程序,我调用siglongjmp以便跳过错误的指令 问题是,我再次希望引起SIGSEGV并转到同一个处理程序,但现在sigsetjmp将返回1 如何重置sigsetjmp 这是我的密码: #include <stdio.h> #include <memory.h> #include <stdlib.h> #include <unistd.h> #includ

我使用sigsetjmp和siglongjmp编写了一个分段错误处理程序。一旦它进入信号处理程序,我调用siglongjmp以便跳过错误的指令

问题是,我再次希望引起SIGSEGV并转到同一个处理程序,但现在sigsetjmp将返回1

如何重置sigsetjmp

这是我的密码:

#include <stdio.h>
#include <memory.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <fcntl.h>
#include <signal.h>
#include <setjmp.h>

sigjmp_buf env, env1;

void SIGSEGV_handler(int signal)
{
  printf("Segmentation fault caught\n");
  siglongjmp(env, 1);
}

int main()
{
 void * allocation;
 size_t size;
 static int devZerofd = -1;
 struct sigaction sa, sa1;

 sa.sa_handler=(void*)SIGSEGV_handler;
 sigaction(SIGSEGV, &sa, NULL);

 if ( devZerofd == -1 ) {
     devZerofd = open("/dev/zero", O_RDWR);
     if ( devZerofd < 0 )
         perror("open() on /dev/zero failed");
  }

 allocation = (caddr_t) mmap(0, 5000, PROT_READ|PROT_NONE, MAP_PRIVATE, devZerofd,  0);

 if ( allocation == (caddr_t)-1 )
    fprintf(stderr, "mmap() failed ");

 if ( mprotect((caddr_t)allocation, 5000, PROT_NONE) < 0 )
     fprintf(stderr, "mprotect failed");
 else
     printf("mprotect done: memory allocated at address %u\n",allocation);

 if(sigsetjmp(env, 1)==0) {
      printf("Causing SIGSEGV: 1\n");
      strcpy(allocation,"Hello, how are you");
  }

  /****** This can't be done again as sigsetjmp won't return 0*****/
  /*

  if(sigsetjmp(env, 1)==0) {
      printf("Causing SIGSEGV: 1\n");
      strcpy(allocation,"Hello, how are you");
  }
   */
 }
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
sigjmp_buf env,env1;
无效SIGSEGV_处理器(int信号)
{
printf(“捕捉到分段错误\n”);
siglongjmp(env,1);
}
int main()
{
无效*分配;
大小;
静态int devZerofd=-1;
结构sigaction sa,sa1;
sa.sa_handler=(void*)SIGSEGV_handler;
sigaction(SIGSEGV,&sa,NULL);
if(devZerofd==-1){
devZerofd=open(“/dev/zero”,O_RDWR);
if(devZerofd<0)
perror(“在/dev/zero上打开()失败”);
}
分配=(caddr_t)mmap(0,5000,保护读取|保护无,映射私有,devZerofd,0);
如果(分配==(caddr_t)-1)
fprintf(stderr,“mmap()失败”);
if(保护((caddr)分配,5000,保护无)<0)
fprintf(标准“mprotect失败”);
其他的
printf(“mprotect done:内存分配在地址%u\n”,分配);
if(sigsetjmp(env,1)==0){
printf(“导致SIGSEGV:1\n”);
strcpy(分配,“你好,你好”);
}
/******无法再次执行此操作,因为sigsetjmp不会返回0*****/
/*
if(sigsetjmp(env,1)==0){
printf(“导致SIGSEGV:1\n”);
strcpy(分配,“你好,你好”);
}
*/
}

您误解了
[sig]setjmp
的工作原理。如果您取消对认为不起作用的代码的注释,编译并运行它,您将看到它实际上起作用了

setjmp
无法通过调用
longjmp
使其返回零。如果您第二次调用
setjmp
本身,即使使用相同的
jmp_buf
(正如您在这里所做的),它第二次也会返回零

顺便说一下,您有一个bug:您没有正确设置
sigaction
参数结构。你应该这样做:

struct sigaction sa;

sa.sa_handler = SIGSEGV_handler;
sigemptyset(&sa.sa_mask);
sa.sa_flags = SA_RESTART;
sigaction(SIGSEGV, &sa, 0);

使用
mmap
有点不合适,但实际上并不是bug。在大多数当前平台上,您不需要
/dev/zero
,只需使用
MAP\u ANON
(某些平台拼写为
MAP\u ANONYMOUS
)和-1 fd参数即可。您应该使用
getpagesize
,然后请求整张页面。

您误解了
[sig]setjmp
的工作原理。如果您取消对认为不起作用的代码的注释,编译并运行它,您将看到它实际上起作用了

setjmp
无法通过调用
longjmp
使其返回零。如果您第二次调用
setjmp
本身,即使使用相同的
jmp_buf
(正如您在这里所做的),它第二次也会返回零

顺便说一下,您有一个bug:您没有正确设置
sigaction
参数结构。你应该这样做:

struct sigaction sa;

sa.sa_handler = SIGSEGV_handler;
sigemptyset(&sa.sa_mask);
sa.sa_flags = SA_RESTART;
sigaction(SIGSEGV, &sa, 0);

使用
mmap
有点不合适,但实际上并不是bug。在大多数当前平台上,您不需要
/dev/zero
,只需使用
MAP\u ANON
(某些平台拼写为
MAP\u ANONYMOUS
)和-1 fd参数即可。您应该使用
getpagesize
,然后请求完整的页面数。

setjmp从longjmp返回1,对吗?所以你的意思是,如果进行了后续调用,它会再次返回0?sau RESTART,你的意思是因为它是可中断函数?但如果没有这一点,它也会起作用:)或多或少,是的。请记住,对
setjmp
的每次调用都可能返回两次:第一次是在控件第一次到达
setjmp
时,第二次是在
setjmp
调用中使用相同的
jmp\u buf
时调用
longjmp
。第一次返回总是返回零。第二个返回返回
longjmp
的第二个参数是什么,除非它是零,否则它将返回一个。但是,当您再次调用setjmp时,将设置一对新的返回,其中第一个返回值再次为零。mmap-PROT_NONE可能是创建分段错误的最简单方法。因为strcpy上的overwrite并不总是给出SIGSEGV,除非您使用类似efence的东西编译它。错误在于您没有初始化
sa_掩码
sa_标志
字段,这意味着您在这些字段中传递了随机数。我的示例展示了如何初始化它们的一个安全的通用选择:这绝不是唯一有效的选择,但我建议使用它,除非您有特定的理由不这样做。特别是,不使用sau重启是危险的,所以只有在需要特定信号来中断系统调用时才应该这样做。不要因为它看起来没有什么区别就忽略它。setjmp从longjmp返回时返回1,对吗?所以你的意思是,如果进行了后续调用,它会再次返回0?sau RESTART,你的意思是因为它是可中断函数?但如果没有这一点,它也会起作用:)或多或少,是的。请记住,对
setjmp
的每次调用都可能返回两次:第一次是在控件第一次到达
setjmp
时,第二次是在
setjmp
调用中使用相同的
jmp\u buf
时调用
longjmp
。第一次返回总是返回零。第二个返回返回
longjmp
的第二个参数是什么,除非它是零,否则它将返回一个。但是,当您再次调用setjmp时,将设置一对新的返回,其中第一个返回值再次为零。mmap-PROT_NONE可能是创建分段错误的最简单方法。因为strcpy上的overwrite并不总是给出SIGSEGV,除非你用efence之类的东西编译它