信号处理函数的问题

小魔菇 2010-09-20 02:48:20
我在程序中故意设置了未分配内存地址的变量 k
对其进行写操作 就一个段错误,以便信号处理函数捕捉到了SIGSEGV Segmentation fault信号

信号处理函数捕捉到信号之后 想修复段错误 所以给变量k分配一段内存空间 但是仍然会引发段错误

不知道哪儿错了 请高手指点一下




#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/resource.h>

#define _CORE_SIZE 256 * 1024 * 1024
static int _core_dump_signals[] = {
SIGABRT, SIGFPE, SIGILL, SIGQUIT, SIGSEGV,
SIGTRAP, SIGSYS, SIGBUS, SIGXCPU, SIGXFSZ,
#ifdef SIGEMT
SIGEMT
#endif
};

#ifndef ARRAY_SIZE
#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
#endif
int *k;
int i = 2;

void _dump_and_restart1(int signo)
{
printf("I am receiving signo: %d\n", signo);
k=(int*)malloc(sizeof(int));
// printf("k=%x\n",k);
}

int main(void)
{
//_daemonize();
struct sigaction act;
int i;

memset(&act, 0, sizeof(act));
act.sa_handler = _dump_and_restart1;
sigfillset(&act.sa_mask);
for (i = 0; i < ARRAY_SIZE(_core_dump_signals); i ++)
sigaction(_core_dump_signals[i], &act, NULL);
sigprocmask(SIG_UNBLOCK, &act.sa_mask, NULL);

*k = 10;
printf("%x\n",k);
return 0;
}


...全文
188 14 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
14 条回复
切换为时间正序
请发表友善的回复…
发表回复
justkk 2010-09-25
  • 打赏
  • 举报
回复
longjmp()的本意是提供一个非局部的跳转
siglongjmp()与它的区别就是可以恢复进程的信号屏蔽

从信号处理函数返回后,只能回到调用信号处理函数时的堆栈状态
如果想回到再之前的一个状态,只能使用longjmp()
小魔菇 2010-09-25
  • 打赏
  • 举报
回复
[Quote=引用 12 楼 justkk 的回复:]

我理解的就是8楼的样子了..
siglongjmp可以跳转到之前保存的上下文,可以实现函数级跳转
[/Quote]

但是为什么要用它来跳转 是因为正常的出流程出问题了 才这样来跳转?
justkk 2010-09-25
  • 打赏
  • 举报
回复
我理解的就是8楼的样子了..
siglongjmp可以跳转到之前保存的上下文,可以实现函数级跳转
小魔菇 2010-09-24
  • 打赏
  • 举报
回复
[Quote=引用 10 楼 justkk 的回复:]

没说你破坏堆栈啊
[/Quote]

那为什么要用siglongjmp才能跳转的回来?
这个函数出现的情形是什么时候?
justkk 2010-09-24
  • 打赏
  • 举报
回复
没说你破坏堆栈啊
小魔菇 2010-09-24
  • 打赏
  • 举报
回复
[Quote=引用 7 楼 eclipse_2 的回复:]

我这样做破坏了堆栈了吗?
[/Quote]

我觉得只要我的信号处理函数写的安全一点 应该不会破坏堆栈吧
justkk 2010-09-21
  • 打赏
  • 举报
回复
猜测 *k = 10需要两步完成
首先提取k的地址,此时为0
然后向地址0写入10,触发SIGSEGV信号
从信号处理函数返回后,继续执行第二步,依然触发SIGSEGV信号

更深入的估计得看汇编了..
小魔菇 2010-09-20
  • 打赏
  • 举报
回复
我这样做破坏了堆栈了吗?
小魔菇 2010-09-20
  • 打赏
  • 举报
回复
[Quote=引用 5 楼 mymtom 的回复:]

试试setjump/longjump
C/C++ code

/*-
* Copyright (C), 1988-2010, Kobus Co., Ltd.
*
* vi:set ts=4 sw=4:
*
* $Id$
*
* $Log$
*/
#ifndef lint
static const char RCSID[] =
"$Id$";
static const char……
[/Quote]

谢谢 但是为什么要这样做?
mymtom 2010-09-20
  • 打赏
  • 举报
回复
试试setjump/longjump

/*-
* Copyright (C), 1988-2010, Kobus Co., Ltd.
*
* vi:set ts=4 sw=4:
*
* $Id$
*
* $Log$
*/
#ifndef lint
static const char RCSID[] =
"$Id$";
static const char RELID[] =
"$" "Date: "__FILE__" "__DATE__" "__TIME__" $";
#endif /* not lint */

/**
* @file ksegv.c
* @brief
*/

#include <stdio.h>
#include <stdlib.h>
#include <setjmp.h>

jmp_buf segv_buf;
int *ptr = 0;

void sig_segv(int sig)
{
ptr = malloc(sizeof(int));
longjmp(segv_buf, 1);
}

int
main(int argc, char *argv[])
{

signal(SIGSEGV, &sig_segv);
setjmp(segv_buf);
*ptr = 10;
printf("%p %d\n", ptr, *ptr);
free(ptr);

return 0;
}
justkk 2010-09-20
  • 打赏
  • 举报
回复
可以借助于siglongjmp()
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>
#include <setjmp.h>

int *k;
sigjmp_buf e;

void foo(int signo)
{
printf("I am receiving signo: %d\n", signo);
k = (int*)malloc(sizeof(int));
printf("1k=%x\n",k);
siglongjmp(e, 1);
}

int main(void)
{
struct sigaction act;

memset(&act, 0, sizeof(act));
sigemptyset(&act.sa_mask);
act.sa_flags = 0;
act.sa_handler = foo;
sigaction(SIGSEGV, &act, NULL);

sigsetjmp(e, 0);

*k = 10;
printf("2k=%x\n",k);
return 0;
}
小魔菇 2010-09-20
  • 打赏
  • 举报
回复
[Quote=引用 2 楼 justkk 的回复:]

哦 想法很新颖的..
应该行不通,试验的结果是频繁调用信号处理函数
感觉信号的触发是在*k = 10的中间,从信号处理函数返回后,不再重新执行提取k的地址
[/Quote]

为什么不再提取k的地址 如何能让编译器再次获取k的地址?
justkk 2010-09-20
  • 打赏
  • 举报
回复
哦 想法很新颖的..
应该行不通,试验的结果是频繁调用信号处理函数
感觉信号的触发是在*k = 10的中间,从信号处理函数返回后,不再重新执行提取k的地址

23,217

社区成员

发帖
与我相关
我的任务
社区描述
Linux/Unix社区 应用程序开发区
社区管理员
  • 应用程序开发区社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

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