Catching segfaults in C

2019-02-06 16:43发布

I have a program that segfaults from pointer arithmetic sometimes. I know this happens, but I can't easily check ahead of time to see whether it segfaults or not - either I can "pre-scan" input data to see if it will cause a segfault (which can be impossible to determine), or I can refit it to not use pointer arithmetic, which would require a significantly larger amount of work, or I can try to catch a segfault. So my question:

1) How, in C, can I catch a segfault? I know something in the OS causes a segfault, but what can a C program do in the event that it segfaults to die a bit more gracefully than just Segmentation fault?

2) How portable is this?

I imagine this is a highly unportable behavior, so if you post any code to catch a segfault, please tell me what it works on. I'm on Mac OS X but I'd like my program to work on as many platforms as it can and I want to see what my options are.

And don't worry - basically all I want to do is print a more user-friendly error message and free some malloc()ed memory, and then die. I'm not planning on just ignoring all segfaults I get and plowing ahead.

8条回答
地球回转人心会变
2楼-- · 2019-02-06 16:43

There's an example of how to catch SIGSEGV and print a stack trace using glibc's backtrace() here:

how to generate a stacktrace when my C++ app crashes

You can use this to catch your segfault and clean up, but be warned: you should not be doing too much stuff in a signal handler, especially things that involve making calls like malloc(). There are a lot of calls that aren't signal safe, and you can end up shooting yourself in the foot if you make, say, a call to malloc from within malloc.

查看更多
forever°为你锁心
3楼-- · 2019-02-06 16:44

Well, SIGSEGV is trappable, and this is POSIX, so it is portable in that sense.

Bu I'm concerned that you seem to want to handle the segfault rather than fix the problem that causes the segfault. If I had to pick whether it was the OS at fault, or my own code, I know which I would choose. I suggest you hunt down that bug, fix it, then write a test case to make sure it never bites you again.

查看更多
放荡不羁爱自由
4楼-- · 2019-02-06 16:46

I think you are trying to solve a problem that doesn't exist. At least you are working on the wrong end. You won't be able to catch a segmentation fault, as this error/exception is thrown by the OS (it is caused by your program, the OS just catches it).

I'd advise you to rethink your strategy regarding the input: Why is it impossible to sanitize it? The most important to do is size checking, for this the C stdlib has appropriate functions. Then of course you'd have to check for valid input regarding the content. Yes, this will probably result in a lot of work, but it's the only way to write a robust program.

EDIT: I'm not much of a C expert, didn't know that even a segmentation fault could be handled by a signal handler. Still, I think it's not the right way to go for the reasons mentioned above.

查看更多
聊天终结者
5楼-- · 2019-02-06 16:50

You'll need to provide a SIGSEGV handler, this one looks quite decent.

查看更多
神经病院院长
6楼-- · 2019-02-06 16:57

You can use the function signal to install a new signal handler for the signal:

   #include <signal.h>
   void (*signal(int signum, void (*sighandler)(int)))(int);

Something like the following code:

signal(SIGINT , clean_exit_on_sig);
signal(SIGABRT , clean_exit_on_sig);
signal(SIGILL , clean_exit_on_sig);
signal(SIGFPE , clean_exit_on_sig);
signal(SIGSEGV, clean_exit_on_sig); // <-- this one is for segmentation fault
signal(SIGTERM , clean_exit_on_sig);

void 
clean_exit_on_sig(int sig_num)
{
        printf ("\n Signal %d received",sig_num);
}
查看更多
祖国的老花朵
7楼-- · 2019-02-06 16:58

You have to define a signal handler. This is done on Unix systems using the function sigaction. I've done this with the same code on Fedora 64- and 32-bit, and on Sun Solaris.

查看更多
登录 后发表回答