Compiler:
➜ ~ /usr/bin/c++ --version
Apple clang version 11.0.0 (clang-1100.0.33.8)
Target: x86_64-apple-darwin19.0.0
Thread model: posix
InstalledDir: /Library/Developer/CommandLineTools/usr/bin
Code:
#include <iostream>
#include <exception>
#include <cstdlib>
void f() {
try {
throw std::runtime_error("Exception message.");
} catch(std::runtime_error& e) {
std::cout << e.what() << std::endl;
throw;
}
}
int main() {
using namespace std;
try {
f();
} catch(std::exception& e) {
cout << e.what() << endl;
terminate();
}
return EXIT_SUCCESS;
}
I found out that if i get rid of the "terminate()" in my catch it would work but i am not sure why that is?
There are three outputs that are produced randomly:
libc++abi.dylib: terminating with uncaught exception of type std::runtime_error: Exception message.
Exception message.
Exception message.
Exception message.
libc++abi.dylib: terminating with uncaught exception of type std::runtime_error: Exception message.
Exception message.
Exception message.
Exception message.
libc++abi.dylib: terminating with uncaught exception of type std::runtime_error: Exception message.
P.S. Sorry, maybe for the incorrect question, I'm a beginner.
For starters, your regular cout print goes to stdout, but the "Terminating with ..." message goes to stderr.
What you observe stems from the fact that your terminal (or IDE) is reading these two output channels and presenting them in one place.
Depending on what algorithm your terminal/IDE uses to merge these two streams, it can happen that the stderr message appears in the places you notice.
If you instead point the streams toward the same file descriptor, your OS will take care of the merging. Run your program as follows:
./my_program 2>&1
Now your terminal will show the messages sequentially with no chance for accidental reordering.
Related
I have the following sample code that throws a std::ios_base::failure and tries to catch it, using clang 4.0 in c++11 mode:
#include <ios>
#include <iostream>
#include <stdexcept>
int
main()
{
try {
throw new std::ios_base::failure( "Bonkers" );
}
catch( std::ios_base::failure &e ) {
std::cout << "Failure " << e.what() << std::endl;
}
catch( ... ) {
std::cout << "Anything" << std::endl;
}
return 0;
}
I compile the program like this:
clang++-4.0 --std=c++11 -g -W -Wall ex.cc -o ex
And I get the output:
Anything
I would have expected for it to catch the specific exception. I tried the same with g++ 5.4, but the same result. Also tried without the c++11 flag, does not help either. Taking out the catch all clause gives me this:
terminate called after throwing an instance of 'std::ios_base::failure[abi:cxx11]*'
So what am I missing, and what can I do to fix this? The abi:cxx11 is also shown when I am NOT using the c++11 flag.
As mentioned in the comments, in C++ you do not need to allocate the exception via new and hence throw the pointer to the exception, as would be done in Java.
Instead you simply construct the exception and throw it:
throw std::ios_base::failure( "Bonkers" );
Then the types of the catch clause will match, and the program will behave as expected.
I'm using MinGW gcc (or g++) 7.1.0 on Windows 10.
Normally, throwing an std::runtime_error shows information like this:
terminate called after throwing an instance of 'std::runtime_error'
what(): MESSAGE
This application has requested the Runtime to terminate it in an unusual way.
Please contact the application's support team for more information.
But the following code only shows the last two lines, and the what() information is lost:
#include <stdexcept>
using namespace std;
int main() {
try {
throw runtime_error("MESSAGE");
} catch (...) {
throw;
}
}
So the code above only outputs:
This application has requested the Runtime to terminate it in an unusual way.
Please contact the application's support team for more information.
The same thing happens if I replace ... with const exception&, const runtime_error& (or without const, without &, or without both).
As I know, throw; rethrows the current caught exception. So why isn't what() shown?
What makes you think that rethrowing exception discards the information given by 'what()'? You never inspect what what() returns after rethrowing. This application has requested... message is shown because you uncaught exception caused program to be terminated. what() content is not supposed to be printed automatically.
You can print value return by what() without any problem:
#include <stdexcept>
#include <iostream>
int main()
{
try
{
try
{
throw ::std::runtime_error("MESSAGE");
}
catch (...)
{
throw;
}
}
catch(::std::exception const & exception)
{
::std::cout << exception.what() << ::std::endl;
}
}
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";
}
From Linux I know that in case a C++ program throws an exception, the exception type and message are printed on the terminal while the program dies. On mac, however, the only thing you get is:
libc++abi.dylib: terminate called throwing an exception
Abort trap: 6
Of course I could run the program in a debugger, but that's usually much more overhead just to see the exception type and message.
Is there any way to enable exception type and message printing on mac with any magic command?
Edit: I know what the correct way is to handle such situations with exception handling. It is more out of curiosity to find out whether the linux behavior can be reproduced on mac.
If you want to guarantee the information of a C++ exception is printed to the console you can add a try/catch block in main() like below.
#include <exception>
#include <iostream>
int main(int argc, char* argv[])
{
try { return mymain(argc, argv); }
catch(std::exception& e)
{
std::cout << "Unhandled exception thrown: " << e.what() << std::endl;
}
}
#include "iostream"
#include "conio.h"
#include "exception"
#include "cstdlib"
using namespace std;
void myunexpected ()
{
cerr << "unexpected called\n";
throw 0; // throws int (in exception-specification)
}
void myfunction () throw (int)
{
throw 'x'; // throws char (not in exception-specification)
}
int main (void)
{
set_unexpected (myunexpected);
try
{
myfunction();
}
catch (int) { cerr << "caught int\n"; }
catch (...) { cerr << "caught other exception (non-compliant compiler?)\n"; }
getch();
return 0;
}
Output(When executed on Visual studio 2008):
caught other exception (non-compliant compiler?)
But, I was expecting the output to be:
unexpected called
caught int
NOTE: I executed this program on Visual Studio 2008.
Yes, as per the Standard the output should be[#1]:
unexpected called
caught int
gcc gives accurate result.
Note that, MSVC is notoriously buggy w.r.t handling exception specifications. Exception specifications are considered a failed experiment.
AFAIK, MSVC does not implement exception specifications, except for the empty ones (throw()/nothrow)
C++03 Standard:
[#1] 15.5.2 The unexpected() function [except.unexpected]
The unexpected() function shall not return, but it can throw (or re-throw) an exception. If it throws a new exception which is allowed by the exception specification which previously was violated, then the search for another handler will continue at the call of the function whose exception specification was violated....