Introduction
In previous post, I discussed about Seg Fault which may happens if the program access memory that is not yet allocated, or invalid.
When an exception occurs and the stack winding process happens, the objects in try block are destroyed, and no longer accessible from within catch block. There is a common practice to design exception class in such a way that accepts data, such as debug message. The manner that we pass data into the exception object could be problematic if not done properly.
In that blog, I passed an object that stores a reference to a string, created in the try block, to an exception object. The reference becomes invalid when the string is destroyed, and thus causing memory issue.
In this blog, I discussed about unhandled exception, which may cause signal abortion.
Concepts
For different compilers, the actions could be slightly different when unhandled exception occurs:
According to Microsoft documentation, "if a matching handler (or ellipsis catch
handler) cannot be found for the current exception, the predefined terminate
run-time function is called. (You can also explicitly call terminate
in any of your handlers.) The default action of terminate
is to call abort
."
For GNU compiler, according information on LLVM docs: "if an unhandled exception occurs, the language runtime will call std::terminate()
, but it is implementation-defined whether the runtime unwinds the stack and calls object destructors first. For example, the GNU C++ unwinder does not call object destructors when an unhandled exception occurs. The reason for this is to improve debuggability: it ensures that std::terminate()
is called from the context of the throw
, so that this context is not lost by unwinding the stack. A runtime will typically implement this by searching for a matching non-cleanup
clause, and aborting if it does not find one, before entering any landingpad blocks".
Notes: unhandled exception is not the cause for seg fault, although the behavior of the program is similar: that is it crashes.
Sample faulty program
The following program throws exception twice.
- the first time,
MyException
is thrown bydivide
function if input denominator is zero - the second time,
MyException
is thrown byredoDivision
function, in input denominator is input as zero again.
However, the program is coded to catch exception in the first time, while fail to catch the second time.
#include <iostream>
using namespace std;
class MyException : public std::exception
{
public:
MyException( const std::string m)
: m_( m )
{}
virtual ~MyException() throw(){};
const char* what() const throw() {
cout<<"location of exception object "<<this<<endl;
return m_.c_str();
}
private:
std::string m_;
};
void redoDivision(){
int denominator;
cout<<"reinput denominator: ";
cin>>denominator;
if (denominator == 0){
throw MyException("you put denominator =0 again !");
}
int nominator;
cout<<"reinput nominator: ";
cin>>nominator;
cout<<"Result: "<<nominator/denominator;
}
void divide(int denominator, int nominator){
try {
if (denominator == 0)
throw MyException("denominator value should not be 0\n ");
cout<<"Result: "<<nominator/denominator;
}
catch (MyException &e){
cout<<e.what();
redoDivision();
throw e;
}
}
int main()
{
int denominator, nominator;
cout<<"read denominator, nominator ";
cin>>denominator>>nominator;
divide(denominator, nominator);
return 0;
}
Output when I run this on godbolt.com:
SIGSEGV indicates segmentation fault.
Program returned: 139
Program stdout
read denominator, nominator location of exception object 0x1c6df50
denominator value should not be 0
reinput denominator: location of exception object 0x1c6e060
Program stderr
terminate called after throwing an instance of 'MyException'
what(): you put denominator =0 again !
Program terminated with signal: SIGSEGV
Output when I run this on www.programiz.com
This page correctly indicates that terminate() function has stopped the program with Aborted
action.
/tmp/75KcDq5xiO.o
read denominator, nominator 0 5
location of exception object 0x142c750
denominator value should not be 0
reinput denominator: 0
terminate called after throwing an instance of 'MyException'
location of exception object 0x142c860
what(): you put denominator =0 again !
Aborted
Output when I run this on Unix SunOS 5-11: Core dumped
./main
read denominator, nominator 0 3
location of exception object 0x100115360
denominator value should not be 0
reinput denominator: 0
terminate called after throwing an instance of 'MyException'
location of exception object 0x1001154a0
what(): you put denominator =0 again !
zsh: IOT instruction (core dumped) ./main