#include <execinfo.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <signal.h>
#include <string.h>
void error_write(const char *filename, const char *string)
{
if(!string) return ;
int len = strlen(string);
FILE *fp = fopen(filename, "a+");
if(fp)
{
fwrite(string, 1, len, fp);
fwrite("\n", 1, 1, fp);
fclose(fp);
}
}
#define LOG_ERROR_WRITE(info) error_write("log.txt", info)
#define ENABLE_DEBUG 1
#if ENABLE_DEBUG == 1
#define MY_DEBUG_ASSERT(expr, msg, value) \
do { \
if(!(expr)) { \
print_trace(); \
while(1); \
} \
} while(0)
#else
#define MY_DEBUG_ASSERT(expr, msg, value)
#endif /* #if ENABLE_DEBUG == 1 */
#define MY_ASSERT_IS_NULL(p) (p) != NULL
#define MY_ASSERT_NULL(p) MY_DEBUG_ASSERT(MY_ASSERT_IS_NULL(p), " NULL Value 0x%lx\n", p)
void crashHandler(int signal)
{
void *bt[20];
int btSize = 20;
char **btStrings;
switch (signal)
{
case SIGINT:
printf("SIGINT Interactive attention signal. \n");
break;
case SIGILL:
printf("SIGILL Illegal instruction. \n");
break;
case SIGABRT:
printf("SIGABRT Abnormal termination. \n");
break;
case SIGFPE:
printf("SIGFPE Erroneous arithmetic operation. \n");
break;
case SIGSEGV:
printf("SIGSEGV Invalid access to storage. \n");
break;
case SIGTERM:
printf("SIGTERM Termination request. \n");
break;
case SIGHUP:
printf("SIGHUP Hangup. \n");
break;
case SIGQUIT:
printf("SIGQUIT Quit. \n");
break;
case SIGTRAP:
printf("SIGTRAP Trace/breakpoint trap. \n");
break;
case SIGKILL:
printf("SIGKILL Killed. \n");
break;
case SIGBUS:
printf("SIGBUS Bus error. \n");
break;
case SIGSYS:
printf("SIGSYS Bad system call. \n");
break;
case SIGPIPE:
printf("SIGPIPE Broken pipe. \n");
break;
case SIGALRM:
printf("SIGALRM Alarm clock. \n");
break;
case SIGURG:
printf("SIGURG Urgent data is available at a socket. \n");
break;
case SIGSTOP:
printf("SIGSTOP Stop, unblockable. \n");
break;
case SIGTSTP:
printf("SIGTSTP Keyboard stop. \n");
break;
case SIGCONT:
printf("SIGCONT Continue. \n");
break;
case SIGCHLD:
printf("SIGCHLD Child terminated or stopped. \n");
break;
case SIGTTIN:
printf("SIGTTIN Background read from control terminal. \n");
break;
case SIGTTOU:
printf("SIGTTOU Background write to control terminal. \n");
break;
case SIGPOLL:
printf("SIGPOLL Pollable event occurred (System V). \n");
break;
case SIGXCPU:
printf("SIGXCPU CPU time limit exceeded. \n");
break;
case SIGXFSZ:
printf("SIGXFSZ File size limit exceeded. \n");
break;
case SIGVTALRM:
printf("SIGVTALRM Virtual timer expired. \n");
break;
case SIGPROF:
printf("SIGPROF Profiling timer expired. \n");
break;
case SIGUSR1:
printf("SIGUSR1 User-defined signal 1. \n");
break;
case SIGUSR2:
printf("SIGUSR2 User-defined signal 2. \n");
break;
case SIGWINCH:
printf("SIGWINCH Window size change (4.3 BSD, Sun). \n");
break;
default:
printf("unkown signal:%d\n", signal);
break;
}
btSize = backtrace(bt, btSize);
btStrings = backtrace_symbols(bt, btSize);
for (int i = 0; i < btSize; i++)
{
// printf("%s\n", btStrings[i]);
LOG_ERROR_WRITE(btStrings[i]);
}
exit(signal);
}
/* Obtain a backtrace and print it to stdout. */
void print_trace(void)
{
void *array[10];
size_t size;
char **strings;
size_t i;
size = backtrace(array, 10);
strings = backtrace_symbols(array, size);
printf("Obtained %zd stack frames.\n", size);
for (i = 0; i < size; i++)
{
// printf("%s\n", strings[i]);
LOG_ERROR_WRITE(strings[i]);
}
free(strings);
}
/* A dummy function to make the backtrace more interesting. */
void dummy_function(void)
{
print_trace();
}
void testCrash()
{
int *a = 0;
int aa = *a;
printf("%d\n", aa);
}
int main(void)
{
int *p = NULL;
signal(SIGSEGV, &crashHandler);
testCrash();
// MY_ASSERT_NULL(p);
// dummy_function();
return 0;
}
网友评论