my code crashed on map.at(), which means it find a inexisted key.
i catch error in my main, but it seems only can catch the info of
EXCEPTION: _Map_base::at
and no location info, which means i need to check all at function.
Is there any methods can catch this kind of error and print where it crash?
here is my code:
#include <iostream>
using namespace std;
void func() {
std::unordered_map<int, int> a;
cout << a.at(2) << endl;
}
void main() {
try {
func();
} catch (const std::exception& ex) {
printf("catch EXCEPTION: %s\n", ex.what()); // the mat at error catch here, How can i print the concrete location - func, in the message??????
}
}
Related
The following code will print 0 and ends:
// version 1
#include<future>
#include<iostream>
using namespace std;
int main(){
promise<int> p;
auto f = p.get_future();
p.set_exception(current_exception());
try {
cout << f.get() << endl;
} catch (const exception& e) {
cout << "caught future set exception\n";
}
return 0;
}
Well, seems p.set_exception(current_exception()); didn't cause any issue. But when I change it to be:
// version 2
#include<cassert>
#include<future>
#include<iostream>
using namespace std;
int main(){
promise<int> p;
auto f = p.get_future();
string msg = "test promise";
async([&] { // new code which version 1 didn't have
try {
throw runtime_error(msg);
} catch (...) {
cout << "caught exception 1\n";
try {
p.set_exception(current_exception());
} catch (...) {
cout << "caught exception 2\n";
}
}
}).wait(); // end new code
try {
cout << f.get() << endl;
} catch (const exception& e) {
cout << "caught future set exception\n";
assert(e.what() == msg);
}
return 0;
}
It will run and print:
caught exception 1
caught future set exception
Just wonder how/when does a std::promise fall into error/exception state so that its get_future().get() will throw exception?
What's the main reason of my version 2 code that p.set_exception() causes f.get() issue, while version 1 code has no problem?
Thanks.
// Example program
#include <iostream>
#include <string>
#include <stdexcept>
void log(const std::exception& e) {
try {
throw e;
}
catch (const std::logic_error& e1) {
std::cout << "logic_error: " << e1.what() << std::endl; // How to get logic_error back once caught?
}
catch (const std::exception& e1) {
std::cout << "exception: " << e1.what() << std::endl;
}
}
int main()
{
try {
throw std::logic_error("sth wrong");
}
catch (const std::exception& e) {
log(e);
}
}
I don't want to add more catch clauses is because I want to have a central place to log detailed exception message, it could be very different across different exceptions.
Is there a way to narrow down the std::exception to derived exception in the catch clause?
You can rethrow the original exception in your log method to preserve its original state. This way everything should work as you would expect it.
Modified log method looks like this:
void log(const std::exception& e) {
try {
throw;
}
catch (const std::logic_error& e1) {
std::cout << "logic_error: " << e1.what() << std::endl;
}
catch (const std::exception& e1) {
std::cout << "exception: " << e1.what() << std::endl;
}
}
See throw expression for more details on how throw e and throw differs in this example.
std::exception::what() is virtual. So you don't need to get back the original type to write the logs. You just have to ensure that what() is redefined for your custom exceptions that inherits std::exception.
This may become:
void log(const std::exception & e)
{
std::cout << e.what() << std::endl;
}
You might use std::rethrow_exception:
void log(std::exception_ptr eptr) {
try {
if (eptr) {
std::rethrow_exception(eptr);
}
}
catch (const std::logic_error& e1) {
std::cout << "logic_error: " << e1.what() << std::endl;
}
catch (const std::exception& e1) {
std::cout << "exception: " << e1.what() << std::endl;
}
}
int main()
{
try {
throw std::logic_error("sth wrong");
}
catch (const std::exception&) { // or even catch (...)
log(std::current_exception());
}
}
You don't have to use only base exceptions provided by the standard library, you can make your own exception hierarchy with the methods you need.
#include <exception>
#include <string>
#include <iostream>
class MyBaseException: public std::exception
{
public:
virtual std::string output() const = 0;
/* Define methods you need here */
};
class MySpecificException : public MyBaseException
{
public:
const char* what() const noexcept override {return "error"; }
std::string output() const override { return "Specific debug output that I want"; }
};
int main(){
try{
throw MySpecificException{};
}catch(const MyBaseException& e){
std::cout << e.output() << '\n';
}catch(const std::exception& e) {
std::cout << e.what() << '\n';
}
}
You can use run time type information to get the type of the execption:
#include <iostream>
#include <string>
#include <stdexcept>
#include <typeinfo>
#if defined(__clang__) || defined(__GNUC__)
#include <cxxabi.h>
#endif
std::string getTypename(const std::exception& e)
{
#if defined(__clang__) || defined(__GNUC__)
// .name() returns a mangled name on gcc and clang
int status;
return abi::__cxa_demangle(typeid( e ).name(), 0, 0, &status);
#else
// visual studio returns a human readable name
return typeid( e ).name();
#endif
}
void log(const std::exception& e) {
std::cout << getTypename( e ) << ": " << e.what() << std::endl;
}
int main()
{
try {
throw std::logic_error("sth wrong");
}
catch (const std::exception& e) {
log(e);
}
}
The getTypename() method may not work on all platforms and you might need to adjust it to your needs. You might want to use boost::core::demangle rather than calling the gcc demangle API directly.
I am new to C++ and wondering how I could catch all possible errors that could happen in my program during run-time. This is for debugging reasons only. To solve possible errors, I would like to have a look at them first.
This would be my idea of how to catch possible errors in a program. I do not throw exceptions, but would like to catch possible errors directly.
#include <iostream>
#include <exception>
#include <stdexcept>
int doBadStuf(int i)
{
// go out of bounce, or make other mistakes
return 10 / i;
}
int main()
{
try
{
int i = doBadStuf(0);
}
catch (std::exception &e)
{
std::cerr << e.what() << '\n';
}
catch (...)
{
std::cerr << "something else";
}
}
I'm working on a fairly lengthy program, and after running fine for awhile, suddenly I'm getting:
terminate called after throwing an instance of 'std::out_of_range'
what(): basic_string::substr
Being new to exception handling, I did some research and found that I would likely get more information by adding the following to my main function:
int main(int argc, char **argv){
try{
//stuff
}
catch(exception const &exc){
cerr << "Caught exception: " << exc.what() << endl;
}
}
The result of this is the following output:
Caught exception: basic_string::substr
This isn't any more useful than the default output; it doesn't tell me anything about the line triggering the core dump (there are many substr calls in my program), the data the substr is attempting to process, etc. Is there a method for displaying information such as this in C++, or is my only option to use a debugger such as gdb?
There are a few ways.
As you said, a debugger - but that won't help you once the code is in production.
Nested exceptions and function try blocks. e.g.:
#include <exception>
#include <stdexcept>
#include <iostream>
#include <sstream>
#include <iomanip>
void bar(std::string& s, int i)
try
{
s.at(i) = 'A';
}
catch(...)
{
std::ostringstream ss;
ss << "error in bar(" << std::quoted(s) << ", " << i << ")";
std::throw_with_nested(std::runtime_error(ss.str()));
}
void foo(std::string& s)
try
{
bar(s, 6);
}
catch(...)
{
std::ostringstream ss;
ss << "error in foo(" << std::quoted(s) << ")";
std::throw_with_nested(std::runtime_error(ss.str()));
}
void stuff()
try
{
std::string s;
foo(s);
}
catch(...)
{
std::throw_with_nested(std::runtime_error("error in stuff()"));
}
void print_exception(std::ostream& os, const std::exception& e, int level = 0)
{
os << std::string(level, ' ') << "exception: " << e.what() << '\n';
try {
std::rethrow_if_nested(e);
} catch(const std::exception& e) {
print_exception(os, e, level+1);
} catch(...) {}
}
int main()
{
try{
stuff();
}
catch(std::exception& e)
{
print_exception(std::cerr, e);
return 127;
}
return 0;
}
sample output:
exception: error in stuff()
exception: error in foo("")
exception: error in bar("", 6)
exception: basic_string::at: __n (which is 6) >= this->size() (which is 0)
You could use boost::stacktrace in place of the above nested exception handling.
http://coliru.stacked-crooked.com/a/f21bd35632a0a036
Is there some way to catch exceptions which are otherwise unhandled (including those thrown outside the catch block)?
I'm not really concerned about all the normal cleanup stuff done with exceptions, just that I can catch it, write it to log/notify the user and exit the program, since the exceptions in these casese are generaly fatal, unrecoverable errors.
something like:
global_catch()
{
MessageBox(NULL,L"Fatal Error", L"A fatal error has occured. Sorry for any inconvience", MB_ICONERROR);
exit(-1);
}
global_catch(Exception *except)
{
MessageBox(NULL,L"Fatal Error", except->ToString(), MB_ICONERROR);
exit(-1);
}
This can be used to catch unexpected exceptions.
catch (...)
{
std::cout << "OMG! an unexpected exception has been caught" << std::endl;
}
Without a try catch block, I don't think you can catch exceptions, so structure your program so the exception thowing code is under the control of a try/catch.
Check out std::set_terminate()
Edit: Here's a full-fledged example with exception matching:
#include <iostream>
#include <exception>
#include <stdexcept>
struct FooException: std::runtime_error {
FooException(const std::string& what): std::runtime_error(what) {}
};
int main() {
std::set_terminate([]() {
try {
std::rethrow_exception(std::current_exception());
} catch (const FooException& e) {
std::cerr << "Unhandled FooException: " << e.what() << std::endl;
} catch (const std::exception& e) {
std::cerr << "Unhandled exception: " << e.what() << std::endl;
} catch (...) {
std::cerr << "Unhandled exception of unknown type" << std::endl;
}
std::abort();
});
throw FooException("Bad things have happened.");
// throw std::runtime_error("Bad things have happened.");
// throw 9001;
}
You can use SetUnhandledExceptionFilter on Windows, which will catch all unhandled SEH exceptions.
Generally this will be sufficient for all your problems as IIRC all the C++ exceptions are implemented as SEH.
Without any catch block, you won't catch any exceptions. You can have a catch(...) block in your main() (and its equivalent in each additional thread). In this catch block you can recover the exception details and you can do something about them, like logging and exit.
However, there are also downside about a general catch(...) block: the system finds that the exception has been handled by you, so it does not give any more help. On Unix/Linux, this help would constitute creating a CORE file, which you could load into the debugger and see the original location of the unexcepted exception. If you are handling it with catch(...) this information would be already lost.
On Windows, there are no CORE files, so I would suggest to have the catch(...) block. From that block, you would typically call a function to resurrect the actual exception:
std::string ResurrectException()
try {
throw;
} catch (const std::exception& e) {
return e.what();
} catch (your_custom_exception_type& e) {
return e.ToString();
} catch(...) {
return "Ünknown exception!";
}
}
int main() {
try {
// your code here
} catch(...) {
std::string message = ResurrectException();
std::cerr << "Fatal exception: " << message << "\n";
}
}
Update: This covers c++98 only.
From More Effective C++ by Meyers (pg 76), you could define a function that gets called when a function generates an exception that is not defined by its exception specification.
void convertUnexpected()
{
// You could redefine the exception here into a known exception
// throw UnexpectedException();
// ... or I suppose you could log an error and exit.
}
In your application register the function:
std::set_unexpected( convertUnexpected );
Your function convertUnexpected() will get called if a function generates an exception that is not defined by its exception specification... which means this only works if you are using exception specifications. ;(
Provided that C++11 is available, this approach may be used (see example from: http://en.cppreference.com/w/cpp/error/rethrow_exception):
#include <iostream>
#include <exception>
void onterminate() {
try {
auto unknown = std::current_exception();
if (unknown) {
std::rethrow_exception(unknown);
} else {
std::cerr << "normal termination" << std::endl;
}
} catch (const std::exception& e) { // for proper `std::` exceptions
std::cerr << "unexpected exception: " << e.what() << std::endl;
} catch (...) { // last resort for things like `throw 1;`
std::cerr << "unknown exception" << std::endl;
}
}
int main () {
std::set_terminate(onterminate); // set custom terminate handler
// code which may throw...
return 0;
}
This approach also allows you to customize console output for unhandled exceptions: to have something like this
unexpected exception: wrong input parameters
Aborted
instead of this:
terminate called after throwing an instance of 'std::logic_error'
what(): wrong input parameters
Aborted
This is what I always do in main()
int main()
{
try
{
// Do Work
}
catch(std::exception const& e)
{
Log(e.what());
// If you are feeling mad (not in main) you could rethrow!
}
catch(...)
{
Log("UNKNOWN EXCEPTION");
// If you are feeling mad (not in main) you could rethrow!
}
}
Use catch (...) in all of your exception barriers (not just the main thread). I suggest that you always rethrow (...) and redirect standard output/error to the log file, as you can't do meaningful RTTI on (...). OTOH, compiler like GCC will output a fairly detailed description about the unhandled exception: the type, the value of what() etc.