概念:
段错误,简单的讲,当我们的C或者C++程序访问了错误的内存地址的时候,就可能出现段错误。
比较典型的段错误有:空指针、数组越界。
空指针异常:
int* pnValue = NULL;
*pnValue = 0;//pnValue指向了错误的0地址。
int value[10] = {0};
value[10] = 11;//有可能发生段错误。
1、为什么需要捕获段错误?
导致程序发生段错误,一般是由于程序写的不够严谨,没有管理好内存。特别是程序越复杂越容易出现这样的错误。因此,我们希望Native代码也能够和Java层代码一样,拥有类似于CrashHandler一样的功能,在发生未知的错误,导致程序crash之前,能够保存相关的信息。而类Unix系统提供了signal这样的功能,保证程序由于段错误之类的非致命错误导致crash,而退出之前,可以接受到相关的signal,从而做一个有益的工作。
2、一个简单的例子:
#include<stdio.h>
#include<signal.h>
#include<time.h>
#include<signal.h>
#include<time.h>
time_t sLast = 0;
static int count = 0;
static struct sigaction sOldAct;
static int count = 0;
static struct sigaction sOldAct;
void handler(int signal)
{
time_t tNow = time(NULL);
if (tNow > 2 + sLast)
{
printf("signal : %d\n", signal);
sLast = tNow;
++count;
if (count > 2)
{
printf("return to sys signal : %d\n", signal);
sOldAct.sa_handler(signal);
}
}
}
{
time_t tNow = time(NULL);
if (tNow > 2 + sLast)
{
printf("signal : %d\n", signal);
sLast = tNow;
++count;
if (count > 2)
{
printf("return to sys signal : %d\n", signal);
sOldAct.sa_handler(signal);
}
}
}
void use_signal()
{
signal(SIGSEGV, handler);
}
{
signal(SIGSEGV, handler);
}
//注册信号处理句柄
void use_sigaction()
{
struct sigaction act;
act.sa_handler = handler;
//act.sa_flags = SA_RESETHAND | SA_NODEFER;
sigaction(SIGSEGV, &act, &sOldAct);
}
void use_sigaction()
{
struct sigaction act;
act.sa_handler = handler;
//act.sa_flags = SA_RESETHAND | SA_NODEFER;
sigaction(SIGSEGV, &act, &sOldAct);
}
//空指针异常测试
void test_null_pointer()
{
int* p = NULL;
*p = 0;
}
void test_null_pointer()
{
int* p = NULL;
*p = 0;
}
//越界测试
void test_array_beyond()
{
char buf[5] = {0};
char buf1[5] = {0};
buf[6] = 0;
}
void test_array_beyond()
{
char buf[5] = {0};
char buf1[5] = {0};
buf[6] = 0;
}
int main(void)
{
//use_signal();
use_sigaction();
//test_array_beyond();
test_null_pointer();
printf("over\n");
return 0;
}
{
//use_signal();
use_sigaction();
//test_array_beyond();
test_null_pointer();
printf("over\n");
return 0;
}
以上程序在程序发生段错误的时候,会进入预先设置好的处理方法中。由于发生段错误后,程序会不断在同一个地方重试,因此,假如处理方法不使用默认的处理方法,或者直接退出程序的话,会不断收到该signal。(假如没有设置SA_RESETHAND,该标识表示执行一次设置的处理方法后,就将处理方法重置为默认的处理方法)
源码路径:https://github.com/SanYuanAndy/native_code/signal