How to catch segmentation fault in Linux?
On Linux we can have these as exceptions, too.
Normally, when your program performs a segmentation fault, it is sent a SIGSEGV
signal. You can set up your own handler for this signal and mitigate the consequences. Of course you should really be sure that you can recover from the situation. In your case, I think, you should debug your code instead.
Back to the topic. I recently encountered a library (short manual) that transforms such signals to exceptions, so you can write code like this:
try
{
*(int*) 0 = 0;
}
catch (std::exception& e)
{
std::cerr << "Exception caught : " << e.what() << std::endl;
}
Didn't check it, though. Works on my x86-64 Gentoo box. It has a platform-specific backend (borrowed from gcc's java implementation), so it can work on many platforms. It just supports x86 and x86-64 out of the box, but you can get backends from libjava, which resides in gcc sources.
Catch Segmentation fault in c++
C++ try-catch
blocks only handle C++ exceptions. Errors like segmentation faults are lower-level, and try-catch ignores these events and behaves the same as if there was no try-catch block.
Is it possible to catch a segfault with try/catch?
No you can`t.
A SEGFAULT
isn't a regular exception.
The code you show is simply undefined behavior, and anything may be happen. There's no guarantee it ends up throwing an exception.
How to recover from segmentation fault on C++?
I suggest that you create a very small program that you make really safe that monitors the buggy program. If the buggy program exits in a way you don't like, restart the program.
Posix example:
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <cstdio>
#include <iostream>
int main(int argc, char* argv[]) {
if(argc < 2) {
std::cerr << "USAGE: " << argv[0] << " program_to_monitor <arguments...>\n";
return 1;
}
while(true) {
pid_t child = fork(); // create a child process
if(child == -1) {
std::perror("fork");
return 1;
}
if(child == 0) {
execvp(argv[1], argv + 1); // start the buggy program
perror(argv[1]); // starting failed
std::exit(0); // exit with 0 to not trigger a retry
}
// Wait for the buggy program to terminate and check the status
// to see if it should be restarted.
if(int wstatus; waitpid(child, &wstatus, 0) != -1) {
if(WIFEXITED(wstatus)) {
if(WEXITSTATUS(wstatus) == 0) return 0; // normal exit, terminate
std::cerr << argv[0] << ": " << argv[1] << " exited with "
<< WEXITSTATUS(wstatus) << '\n';
}
if(WIFSIGNALED(wstatus)) {
std::cerr << argv[0] << ": " << argv[1]
<< " terminated by signal " << WTERMSIG(wstatus);
if(WCOREDUMP(wstatus)) std::cout << " (core dumped)";
std::cout << '\n';
}
std::cout << argv[0] << ": Restarting " << argv[1] << '\n';
} else {
std::perror("wait");
break;
}
}
}
I get a segmentation fault instead of an exception
Since segfaults are not caused (directly) the the software, but rather by the processor detecting that you are trying to access invalid memory (or access memory in an invalid way - e.g writing to memory that is write-protected, executing memory that isn't supposed to be executed, etc), it is not "catchable" with try/catch
, which is designed to catch software that throws an exception. They are both called exceptions, but they originate at different levels of the software/hardware of the system.
Technically, you can catch segfaults with a signal handler for SIGSEGV
. However, as Ivaylo explains, it's is not, typically, allowed to just "try again" if you get a segfault. The signal hander for SIGSEGV
is allowed to longjmp
or exit
, but shouldn't just return.
Read more about signals here:
http://www.alexonlinux.com/signal-handling-in-linux
Typical C++ exceptions (result of throw
) can be retried without problem (of course, the same exception may be thrown again, of course.
Segmentation fault handling
The default action for things like SIGSEGV
is to terminate your process but as you've installed a handler for it, it'll call your handler overriding the default behavior. But the problem is segfaulting instruction may be retried after your handler finishes and if you haven't taken measures to fix the first seg fault, the retried instruction will again fault and it goes on and on.
So first spot the instruction that resulted in SIGSEGV
and try to fix it (you can call something like backtrace()
in the handler and see for yourself what went wrong)
Also, the POSIX standard says that,
The behavior of a process is undefined after it returns normally from
a signal-catching function for a [XSI] SIGBUS, SIGFPE, SIGILL, or
SIGSEGV signal that was not generated by kill(), [RTS] sigqueue(),
or raise().
So, the ideal thing to do is to fix your segfault in the first place. Handler for segfault is not meant to bypass the underlying error condition
So the best suggestion would be- Don't catch the SIGSEGV
. Let it dump core. Analyze the core. Fix the invalid memory reference and there you go!
try catch fails to handle segmentation fault inside a pthread
Instead of using the operator[]
(which does not perform bounds checking) and will result in undefined behavior if the vector does not have an element at the specified index, you can use the at()
member function.
at( size_type pos );
This function:
Returns a reference to the element at specified location pos, with bounds checking.
If
pos
is not within the range of the container, an exception of typestd::out_of_range
is thrown.
Since an exception is thrown with at()
, you can catch
it.
The usage in your case will be:
int firing_crash=cdp->firing_data.at(0).size();
Try/Catch a segmentation fault on Linux
If you have a scenario where many pointers across your app reference the same limited-lifetime objects, a popular solution is to use boost smart pointers. Edit: in C++11, both of these types are available in the standard library
You would want to use shared_ptr
for pointer(s) that are responsible for the lifetime of your object and weak_ptr
for the other pointers, which may become invalid. You'll see that weak_ptr
has the validity check you're asking for built in.
Related Topics
When Is a Private Constructor Not a Private Constructor
C++: What Regex Library Should I Use
How to Read a Cmake Variable in C++ Source Code
Why Do We Not Have a Virtual Constructor in C++
C++ - Why Is Boost::Hash_Combine the Best Way to Combine Hash-Values
Is There a Reason to Call Delete in C++ When a Program Is Exiting Anyway
How to Select a Range of Values in a Switch Statement
String Literal Address Across Translation Units
Mixing Cout and Printf For Faster Output
Foreach Macro on Macros Arguments
What's a Very Easy C++ Profiler (Vc++)
Pinpointing "Conditional Jump or Move Depends on Uninitialized Value(S)" Valgrind Message