Why do unhandled exceptions cause a segmentation fault? - c++

Here is a minimum example:
[joel#maison various] (master *)$ cat throw.cpp
#include <iostream>
int main(int argc, char* argv[])
{
throw("pouet pouet");
}
[joel#maison various] (master *)$ ./a.out
terminate called after throwing an instance of 'char const*'
Aborted (core dumped)
Reading the docs, it seems like the default terminate handler is abort(). I couldn't find anything about triggering a segfault in the abort man page.

Throwing an exception and not handling it calls abort() which raises SIGABRT.
You can verify it with the following
#include <iostream>
#include <stdexcept>
#include <signal.h>
extern "C" void handle_sigabrt(int)
{
std::cout << "Handling and then returning (exiting)" << std::endl;
}
int main()
{
signal(SIGABRT, &handle_sigabrt);
throw("pouet pouet");
}
Demo

Related

Why is there an access violation on connecting to MongoDB from C++?

When I try to run this little piece of code
#include <iostream>
#include <bsoncxx/builder/stream/document.hpp>
#include <bsoncxx/json.hpp>
#include <mongocxx/client.hpp>
#include <mongocxx/instance.hpp>
int main(int argc, char **argv)
{
mongocxx::client client{mongocxx::uri{}};
mongocxx::database db = client["xyz"];
std::cout << "Connected to xyz." << std::endl;
}
I always get this warning
Exception thrown at 0x00007FFF7815F1FD (libmongoc-1.0.dll) in Test.exe: 0xC0000005: Access violation writing location 0x0000000000000020.
Can someone help?
I fixed it by adding
mongocxx::instance instance{};
as the first line of code in the main function.

Why signal handler for SIGSEGV doesn't catch my C++ throw exception?

I was trying to see if SIGSEGV signal hander could help to deal with unhandled exception of C++, I experiment it:
#include <stdio.h>
#include <execinfo.h>
#include <signal.h>
#include <stdlib.h>
#include <unistd.h>
void handler(int sig) {
void *array[10];
size_t size = backtrace(array, 10);
fprintf(stderr, "Error: signal %d:\n", sig);
backtrace_symbols_fd(array, size, STDERR_FILENO);
exit(1);
}
int main()
{
signal(SIGSEGV, handler);
throw 1;
}
$ g++ -g h.cpp -rdynamic && ./a.out
terminate called after throwing an instance of 'int'
Aborted (Core dump)
Well, the program doesn't print crash call stack back trace as I expected. My question is:
As long as it terminates, does it through out any signals like SIGSEGV?
Is there a system call or posix api that could catch even C++ exceptions and prints out the call stack?
Thanks!
You can install a termination handler with std::set_terminate - the installed handler will then be invoked for unhandled exception. There is no strong guarantee, but there is a great chance that the invocation of abort that causes invocation of the termination handler is occurring on the top of the stack that threw the exception and thus you can still collect a backtrace.
Also, you can install a handler for SIGABRT, that will work as well:
#include <execinfo.h>
#include <signal.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
void handler(int sig, siginfo_t*, void*) {
void *array[10];
size_t size = backtrace(array, 10);
fprintf(stderr, "Error: signal %d:\n", sig);
backtrace_symbols_fd(array, size, STDERR_FILENO);
exit(1);
}
void terminate_handler()
{
}
int main()
{
struct sigaction new_sigaction, old_sigaction;
new_sigaction.sa_flags = SA_SIGINFO;
new_sigaction.sa_sigaction = handler;
sigaction(SIGABRT, &new_sigaction, &old_sigaction);
throw 1;
}
I'd personally prefer the termination handler, since in that case you explicitly know the cause. If the SIGABRT handler is invoked you must understand if this is because an unhandled exception invoked abort() or the signal was sent by other means.
I think you need to do
raise(SIGSEGV)
if you want to end up in your handler:
#include <stdio.h>
#include <execinfo.h>
#include <signal.h>
#include <stdlib.h>
#include <unistd.h>
void handler(int sig) {
void *array[10];
size_t size = backtrace(array, 10);
fprintf(stderr, "Error: signal %d:\n", sig);
backtrace_symbols_fd(array, size, STDERR_FILENO);
exit(1);
}
int main()
{
signal(SIGSEGV, handler);
raise(SIGSEGV);
}

$ symbol causes program to crash

Here is my program:
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string>
#include <iostream>
int main()
{
std::string hash = crypt("asd123","$2a$13$IP4FT4gf123I5bT6o4123123123123nbEXFqo.Oa123");
std::cout << hash;
}
Running this causes the error
terminate called after throwing an instance of 'std::logic_error'
what(): basic_string::_M_construct null not valid
Aborted (core dumped)
but if I remove the $ from the salt it runs fine.
The error message tells you that crypt returns a nullpointer for the given arguments. Most likely that's its way to signal failure. You need to check for that.
You can find out more about crypt by (1) finding documentation of the function, and (2) reading it.
For example, you can google “unistd crypt”.
And it so happens that the documentation specifies the valid set of characters you can use, in a nice table.

Why is my terminate handler never invoked?

I have read that one can call std::set_terminate() to use own function as global exception handler, which catches all unhandled exceptions.
Simplified code of my program:
#include <exception>
#include <stdexcept>
#include <iostream>
void my_terminate_handler()
{
std::cerr << "Terminate handler" << std::endl;
std::cin.get();
std::abort();
}
int main()
{
std::set_terminate(my_terminate_handler);
int i = 1;
i--;
std::cout << 1/i << std::endl;
return 0;
}
Why my_terminate_handler() never invoked? Both in VC++ 2013, 2015 RC and gcc++-4.8.
The terminate handler will be called if the program calls terminate. This can happen for various reasons - including an uncaught exception - but division by zero isn't one of those reasons. That gives undefined behaviour; typically, it raises a signal (not a C++ exception), and you'd need to install a signal handler, not a terminate handler, to catch that.
Because there is no uncaught exception in your code. Add one and it gets executed:
#include <exception>
#include <stdexcept>
#include <iostream>
void my_terminate_handler()
{
std::cerr << "Terminate handler" << std::endl;
}
int main()
{
std::set_terminate(my_terminate_handler);
throw "cake";
}

Does the stack get unwound when a SIGABRT occurs?

Does the stack get unwound (destructors run) when a SIGABRT occurs in C++?
Thanks.
No:
$ cat test.cc
#include <iostream>
#include <sys/types.h>
#include <signal.h>
class Test {
public:
~Test() { std::cout << "~Test called" << std::endl; }
};
int main(int argc, char *argv[])
{
Test t = Test();
if (argc > 1) {
kill(0, SIGABRT);
}
return 0;
}
$ g++ test.cc
$ ./a.out
~Test called
$ ./a.out 1
Aborted
This answer indicates that destructors aren't called.
No, only exceptions trigger stack unwinding. Signals are part of POSIX, which is a C API, so it's not "aware of" C++ facilities such as exceptions.
The signal(3) man page on my Mac OS X box says
No Name Default Action Description
...
6 SIGABRT create core image abort program (formerly SIGIOT)
which suggests to me that the default is to not unwind...
the signal SIGABRT is used for making core file of running application some time. We some time use this signal to debug application. And as far as I know Destructors are not called by this signal.