Mar*_*son 14 c signals exception-handling segmentation-fault
在Segmentation Fault错误之后,是否可以恢复C程序的正常执行流程?
struct A {
int x;
};
A* a = 0;
a->x = 123; // this is where segmentation violation occurs
// after handling the error I want to get back here:
printf("normal execution");
// the rest of my source code....
Run Code Online (Sandbox Code Playgroud)
我想要一个类似于NullPointerException的机制,它存在于Java,C#等中.
注意:请不要告诉我C++中有一个异常处理机制,因为我知道,不要告诉我在分配之前我应该检查每个指针.
我真正想要实现的是恢复正常的执行流程,如上例所示.我知道可以使用POSIX信号进行一些操作.应该怎么样?其他想法?
nos*_*nos 23
#include <unistd.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/mman.h>
#include <signal.h>
#include <stdlib.h>
#include <ucontext.h>
void safe_func(void)
{
puts("Safe now ?");
exit(0); //can't return to main, it's where the segfault occured.
}
void
handler (int cause, siginfo_t * info, void *uap)
{
//For test. Never ever call stdio functions in a signal handler otherwise*/
printf ("SIGSEGV raised at address %p\n", info->si_addr);
ucontext_t *context = uap;
/*On my particular system, compiled with gcc -O2, the offending instruction
generated for "*f = 16;" is 6 bytes. Lets try to set the instruction
pointer to the next instruction (general register 14 is EIP, on linux x86) */
context->uc_mcontext.gregs[14] += 6;
//alternativly, try to jump to a "safe place"
//context->uc_mcontext.gregs[14] = (unsigned int)safe_func;
}
int
main (int argc, char *argv[])
{
struct sigaction sa;
sa.sa_sigaction = handler;
int *f = NULL;
sigemptyset (&sa.sa_mask);
sa.sa_flags = SA_SIGINFO;
if (sigaction (SIGSEGV, &sa, 0)) {
perror ("sigaction");
exit(1);
}
//cause a segfault
*f = 16;
puts("Still Alive");
return 0;
}
$ ./a.out
SIGSEGV raised at address (nil)
Still Alive
Run Code Online (Sandbox Code Playgroud)
如果我在生产代码中看到这样的东西,我会用蝙蝠击败某人,但这是一个丑陋,有趣的黑客.您不知道段错误是否已损坏您的某些数据,您将无法恢复并且知道现在一切正常,没有可行的方法来执行此操作.你可以做的唯一温和的事情是尝试记录错误(直接使用write(),而不是任何stdio函数 - 它们不是信号安全的)并且可能重启程序.对于那些情况,你最好写一个监视子进程退出的超级进程进程,记录它并启动一个新的子进程.
您可以使用信号处理程序捕获分段错误,并决定继续执行程序(风险自负).
信号名称是SIGSEGV.
您必须sigaction()从signal.h标题中使用该函数.
基本上,它的工作方式如下:
struct sigaction sa1;
struct sigaction sa2;
sa1.sa_handler = your_handler_func;
sa1.sa_flags = 0;
sigemptyset( &sa1.sa_mask );
sigaction( SIGSEGV, &sa1, &sa2 );
Run Code Online (Sandbox Code Playgroud)
这是处理函数的原型:
void your_handler_func( int id );
Run Code Online (Sandbox Code Playgroud)
如您所见,您无需返回.程序的执行将继续,除非您决定自己从处理程序中停止它.