How do I catch wrong array reference in C++? Why doesn't the following code work:
#include <exception>
int * problemNum = new int;
int (* p [100])() = {problem1, problem2, problem3};
...
try {
cout << (*p[*problemNum-1])();
}
catch (exception){
cout << "No such problem";
}
My compiler says: Unhandled exception at 0xcccccccc in Euler.exe: 0xC0000005: Access violation. when I initiate bad reference by inputting 0 as *problemNum.
alamar is right - C++ won't catch exceptions with this type of array.
Use an STL vector instead:
#include <exception>
#include <vector>
int * problemNum = new int;
std::vector<int(*)()> p;
p.push_back(problem1);
p.push_back(problem2);
p.push_back(problem3);
...
try {
cout << p.at(*problemNum-1)();
}
catch (exception){
cout << "No such problem";
}
Becauce C++ can't handle such errors with its exception mechanism.
See Defective C++ on that issue.
Use sigaction(2).
sigaction - examine and change a signal action
SYNOPSIS
#include <signal.h>
int sigaction(int signum, const struct sigaction *act,
struct sigaction *oldact);
DESCRIPTION
The sigaction() system call is used to change the action taken by a process on receipt of a specific
signal.
signum specifies the signal and can be any valid signal except SIGKILL and SIGSTOP.
If act is non-null, the new action for signal signum is installed from act. If oldact is non-null,
the previous action is saved in oldact.
The sigaction structure is defined as something like:
struct sigaction {
void (*sa_handler)(int);
void (*sa_sigaction)(int, siginfo_t *, void *);
sigset_t sa_mask;
int sa_flags;
void (*sa_restorer)(void);
};
You need to catch SIGSEGV, you can attach your own handler (function which gets called when illegal memory access is performed).
Related
I try to catch a termination signal to my code to write a restart file before exiting. My solution is based on this answer.
#include <exception>
#include <csignal>
#include <iostream>
class InterruptException : public std::exception
{
public:
InterruptException(int _s) : signal_(_s) { }
int signal() const noexcept
{
return this->signal_;
}
private:
int signal_;
};
/// method to throw exception at signal interrupt
void sig_to_exception(int s)
{
throw InterruptException(s);
}
int main()
{
// activate signal handling
struct sigaction sigIntHandler;
sigIntHandler.sa_handler = sig_to_exception;
sigemptyset(&sigIntHandler.sa_mask);
sigIntHandler.sa_flags = 0;
sigaction(SIGINT, &sigIntHandler, NULL);
try
{
for (std::size_t i = 0; i < 100000000; ++i)
{
std::cout << i << std::endl;
}
}
catch (const InterruptException& e)
{
std::cout << "Received signal " << e.signal() << std::endl;
std::exit(1);
}
catch(...)
{
std::cout << "Other catch!" << std::endl;
}
}
The exception gets thrown fine, however, my catch block does not catch it. The program terminates with an uncaught exception InterruptException. I tried with clang and gcc on MacOS. Any idea why the exception is not caught correctly?
Thanks
Output when compiled with g++ 7.3.0:
terminate called after throwing an instance of 'InterruptException'
what(): std::exception
Abort trap: 6
Output when compiled with Apple LLVM 9.0.0
libc++abi.dylib: terminating with uncaught exception of type InterruptException: std::exception
PS: It seems when I compile with Apple LLVM the exception gets caught sometimes, but not all the time, which makes this even weirder.
There is very little that you can reliably do in a signal handler. In particular, you cannot throw an exception. The code in the question (and the "answer" that it links to) relies, at best, on compiler/OS-specific behavior. For the limits on what you can do in a signal handler, see this.
Note that the link above refers to signal, which is standard C. sigaction is not standard C, it's POSIX, and the C++ language definition doesn't impose any requirements on a program that uses it.
On most system the stack frame used by the signal handler is not a standard function stack frame as defined by the compiler for function calls.
So throwing out of a sig handler is not supported.
Stack frame for signal handling in the Linux Kernel
From the discussion in the linked question, on a linux system they are not even using the same stack for the stack frame and returning requires jumping back to a system function to restore the original user stack.
Unless the OS is specifically designed to handle exceptions then this is not going to work.
The rule of thumb for signal handlers is to do as little as possible in a signal handler. Set a global flag that can be detected by your normal code then check that flag periodically in your normal code to see when the signal has happened.
I'm currently working on a project running on a heavily modified version of Linux patched to be able to access a VMEbus. Most of the bus-handling is done, I have a VMEAccess class that uses mmap to write at a specific address of /dev/mem so a driver can pull that data and push it onto the bus.
When the program starts, it has no idea where the slave board it's looking for is located on the bus so it must find it by poking around: it tries to read every address one by one, if a device is connected there the read method returns some data but if there isn't anything connected a SIGBUS signal will be sent to the program.
I tried several solutions (mostly using signal handling) but after some time, I decided on using jumps. The first longjmp() call works fine but the second call to VMEAccess::readWord() gives me a Bus Error even though my handler should prevent the program from crashing.
Here's my code:
#include <iostream>
#include <string>
#include <sstream>
#include <csignal>
#include <cstdlib>
#include <csignal>
#include <csetjmp>
#include "types.h"
#include "VME_access.h"
VMEAccess *busVME;
int main(int argc, char const *argv[]);
void catch_sigbus (int sig);
void exit_function(int sig);
volatile BOOL bus_error;
volatile UDWORD offset;
jmp_buf env;
int main(int argc, char const *argv[])
{
sigemptyset(&sigBusHandler.sa_mask);
struct sigaction sigIntHandler;
sigIntHandler.sa_handler = exit_function;
sigemptyset(&sigIntHandler.sa_mask);
sigIntHandler.sa_flags = 0;
sigaction(SIGINT, &sigIntHandler, NULL);
/* */
struct sigaction sigBusHandler;
sigBusHandler.sa_handler = catch_sigbus;
sigemptyset(&sigBusHandler.sa_mask);
sigBusHandler.sa_flags = 0;
sigaction(SIGBUS, &sigBusHandler, NULL);
busVME = new VMEAccess(VME_SHORT);
offset = 0x01FE;
setjmp(env);
printf("%d\n", sigismember(&sigBusHandler.sa_mask, SIGBUS));
busVME->readWord(offset);
sleep(1);
printf("%#08x\n", offset+0xC1000000);
return 0;
}
void catch_sigbus (int sig)
{
offset++;
printf("%#08x\n", offset);
longjmp(env, 1);
}
void exit_function(int sig)
{
delete busVME;
exit(0);
}
As mentioned in the comments, using longjmp in a signal handler is a bad idea. After doing the jump out of a signal handler your program is effectively still in the signal handler. So calling non-async-signal-safe functions leads to undefined behavior for example. Using siglongjmp won't really help here, quoting man signal-safety:
If a signal handler interrupts the execution of an unsafe function, and the handler terminates via a call to longjmp(3) or siglongjmp(3) and the program subsequently calls an unsafe function, then the behavior of the program is undefined.
And just for example, this (siglongjmp) did cause some problems in libcurl code in the past, see here: error: longjmp causes uninitialized stack frame
I'd suggest to use a regular loop and modify the exit condition in the signal handler (you modify the offset there anyway) instead. Something like the following (pseudo-code):
int had_sigbus = 0;
int main(int argc, char const *argv[])
{
...
for (offset = 0x01FE; offset is sane; ++offset) {
had_sigbus = 0;
probe(offset);
if (!had_sigbus) {
// found
break;
}
}
...
}
void catch_sigbus(int)
{
had_sigbus = 1;
}
This way it's immediately obvious that there is a loop, and the whole logic is much easier to follow. And there are no jumps, so it should work for more than one probe :) But obviously probe() must handle the failed call (the one interrupted with SIGBUS) internally too - and probably return an error. If it does return an error using the had_sigbus function might be not necessary at all.
Approximately the code is this:
#include <signal.h>
void SegmentationFaultHandler( int signal ) {
if ( signal == SIGSEGV ) {
// how to check here if it's actual null pointer?
Throw( NullPointerException, "Object pointer not set to an instance of an object." );
}
else
Throw( InvalidOperationException, "Signal has been intercepted by wrong function." );
}
int main( ) {
signal( SIGSEGV, SegmentationFaultHandler );
try {
int *i = null;
*i = 0;
...
How can I check if I didn't double check a pointer, or just accessed uninitialized data and deference it?
I know it's possible, because debuggers can know which address the program tried to access.
It appears that you can retrieve PEXCEPTION_POINTERS inside your handler using _pxcptinfoptrs global variable which is declared inside signal.h. Then use this pointer as in below examples.
static void sigsegv_handler(int signo)
{
PEXCEPTION_POINTERS excptr = _pxcptinfoptrs;
if (excptr != NULL) {
}
// ...
}
Vectored Exception Handler
Under windows you can use Vectored Exception Handler. You handler will look as follows:
LONG WINAPI ExceptionFilter( struct _EXCEPTION_POINTERS * pExceptionPointers ) {
then:
pExceptionPointers->ExceptionRecord->ExceptionCode
is you exception code, EXCEPTION_ACCESS_VIOLATION is when you access invalid memory.
pExceptionPointers->ExceptionRecord->ExceptionInformation[0] == 0
is true when read operation was done
pExceptionPointers->ExceptionRecord->ExceptionInformation[0] == 1
is for write operation
pExceptionPointers->ExceptionRecord->ExceptionInformation[1]
is the address which was being read/written when exception happend
Structured Exception filtering
If you cannot use vectored exception handler then you may add __try/__except at the lowest level of your code, ie. in main() or where you thread function is being exectured:
__try {
// Code which might cause access violation or any other hardware exceptions
}
__except(ExceptionFilter(GetExceptionInformation())) {
}
I would like to know if there is any trivial way of destroying an object that was created in main() after the application just crashed (or was interrupted, or some other. See the code:
#include <iostream>
#include <signal.h>
#include <stdlib.h>
class TestClass {
public:
TestClass() { std::cerr << "Constructor" << std::endl; }
~TestClass() { std::cerr << "Destructor" << std::endl; }
};
void signal_handler(int signum) {
std::cerr << "Signal caught " << signum << std::endl;
exit(1);
}
int main() {
TestClass a;
struct sigaction new_action, old_action;
new_action.sa_handler = signal_handler;
sigemptyset (&new_action.sa_mask);
new_action.sa_flags = 0;
sigaction (SIGSEGV, NULL, &old_action);
if (old_action.sa_handler != SIG_IGN)
{
sigaction (SIGSEGV, &new_action, NULL);
}
// CRASH !!!
int* p = 0; *p = 0;
}
So, I install a signal handler, which upon execution shall do some cleanup, and just exit afterwards. Obviously, it is a big application, so I'd like to call the destructor of my classes which have created temporary files (theoretically speaking).
It would be easy to allocate it dynamically and in the signal_handler just free it (in order to call the destructor), but that involves some extra work.
And also, it could be a global object, but I want to avoid the global initialization order issue ...
You could try to orchestrate an orderly shutdown on SIGSEGV. It's not without its pitfalls, but start here: Is it possible to terminate only the one thread on receiving a SIGSEGV?
You could try to terminate the one offending thread in your signal handler, and set a global flag to say "We're screwed, time to shut down." Then in your main message loop, check the flag and break out if it's set.
In the code below i use try/catch in the python module code. In the try block i have a simple error (memory access violation) and trying to catch the corresponding exception and to terminate the program quietly without generation of the .stackdump file. However the latter is still generated what implies that try/catch construct does not do its job. How could i avoid generating .stackdump file and exit the program without errors when the improper operation (like one in the code) is met?
P.S. i'm compiling the code in cygwin with gcc and boost.python
It is interesting that it doesn't work only in case x[3]=2, but works for all other cases: e.g. x[4]=2 or x[20]=2 or, obviously, x[2]=2.
#include <boost/python.hpp>
#include <iostream>
#include <iomanip>
using namespace std;
using namespace boost::python;
class Hello
{
std::string _msg;
public:
Hello(std::string msg){_msg = msg;}
void run(){
try{
double* x;
x = new double[3];
x[3] = 2.0;
delete [] x;
}catch(...){ exit(0); }
}
};
BOOST_PYTHON_MODULE(xyz)
{
class_<Hello>("Hello", init<std::string>())
.def("run",&Hello::run)
;
}
EDIT:
According to what Maciek has suggested i tried the following trick:
Make signal handling function to throw an exception, but not exit
void sig_action(int signo) {
std::cout << "SIGNAL " << signo << std::endl;
throw 1;
// exit(0);
}
And now try to enclose a possibly problematic function in try/catch block (signal function is placed in class constructor):
class Hello
{
std::string _msg;
public:
Hello(std::string msg){
_msg = msg;
signal(SIGABRT, sig_action);
signal(SIGSEGV, sig_action);
}
void set(std::string msg) { this->_msg = msg; }
std::string greet() { return _msg; }
void run(){
try{
double* x;
x = new double[3];
x[3] = 2.0;
delete [] x;
}catch(...){ cout<<"error in function run()\n"; exit(0); }
}
};
However such a trick doesn't work as i expected it produces the following output:
SIGNAL 6
terminate called after throwing an instance of 'int'
SIGNAL 6
terminate called recursively
SIGNAL 6
terminate called recursively
....
(and many more times the same)
So the exception is thrown, but everything finishes before it has been caught. Is there any way to let it be caught before terminating the process?
You can only catch exceptions that are thrown. An invalid pointer access doesn’t throw an exception, it simply causes undefined behaviour, and in your particular case it results in a stack dump.
If you want to catch such a situation situation, use std::vector and the at function to access items. This will throw std::out_of_range when used with an invalid index. However, it’s usually better to avoid the possibility of such accesses a priori since they are usually indicative of a bug in your program, and bugs should not be handled via exceptions, they should be removed from the code.
On linux core dumps are generated by signal handlers with default action set to core (SIGABRT, SIGSEGV, ...). If you want to avoid core dump you can always capture/ignore those signals. It should work on Cygwin stackdumps as well. But you will still probably get some nasty message as output.
EDIT:
#include <signal.h>
// [...]
void sig_action(int signo) {
std::cout << "SIGNAL " << signo << std::endl;
exit(0);
}
int main(int argc, char* argv[]) {
signal(SIGABRT, sig_action);
signal(SIGSEGV, sig_action);
Hello h("msg");
h.run();
}