I need to create an exception handling, in that I also asked to print the status of the operation like
"file open : The operation completed successfully"
"file close: The operation completed successfully",
etc.
Is there any macro for this like __LINE__,__FUNCTION__,__FILE__?
Or is there any boost function available to do this?
I think the answer is that you want to stringify the expression you are evaluating?
Code:
#include <stdexcept>
#include <sstream>
#include <iostream>
void check_result(bool result, const char* file, int line_number, const char* line_contents)
{
if (!result) {
//for example:
std::stringstream ss;
ss << "Failed: " << line_contents << " in " << file << ' ' << line_number;
throw std::runtime_error(ss.str());
}
}
#define CALL_AND_CHECK(expression) check_result((expression), __FILE__, __LINE__, #expression)
bool foobar(bool b) { return b; }
int main()
{
try {
CALL_AND_CHECK(foobar(true));
CALL_AND_CHECK(foobar(false));
} catch (const std::exception& e) {
std::cout << e.what() << '\n';
}
}
Both __LINE__ and __FILE__ are available in C++, just like in C. The only caveat is that they are macros, expanded at compile-time, so if you stick them in macros or templates they may or may not do what you expect.
I'm not sure what exactly you're asking but here is a code sample from my own library:
/**
* \brief Convenient alias to create an exception.
*/
#define EXCEPTION(type,msg) type((msg), __FUNCTION__, __FILE__, __LINE__)
Basically, this allows me to write:
throw EXCEPTION(InvalidParameterException, "The foo parameter is not valid");
Of course here, InvalidParameterException is a class I designed that takes extra parameters to hold the function, the file and the line where the exception was created.
It has the following constructor:
InvalidParameterException::InvalidParameterException(
const std::string& message,
const std::string& function,
const std::string& file,
int line);
Of course, if you don't want to throw an exception but just output something to, say a logfile, you can obviously use the same "trick".
Hope this helps.
Related
I know it's a simple question, but I'm looking to get my C++ groove on. I would imagine some sort of abort function could be used. But I don't think that'll return any text like die('hello'); would.
There is no "print a message, then exit" in C or C++. You can quite easily write your own function for die (or panic, as I prefer to call it), something like:
void die(const std::string& msg)
{
std::cerr << msg << std::endl;
exit(1);
}
Or, if you want to avoid the problems with creating a string, which may fail under low memory conditons:
void die(const char *msg)
...
(the rest should be the same as above). The drawback here is that you can't trivially concatenate strings, e.g. die(std::string("Could not open file ") + filename); won't work with const char *.
A function that does var_dump is much harder, as there is no direct way to actually fetch the content of a variable of a an arbitrary type, or an array, in C++. You could perhaps do something like this:
template<typename T>
void var_dump(const T& var)
{
std::cout << var << endl;
}
template<typename T, size_t N>
void var_dump(const T (&var)[N])
{
for(i : var)
{
std::cout << i << endl;
}
}
The latter is a bit like this PHP code: foreach($var as $i) echo $i . "\n";. And I may have the syntax slightly wrong, not sure.
I wouldn’t recommend calling std::abort, std::exit or anything like that.
It’s brute-force, and the semantics for proper cleanup are very complicated. You are essentially leaving (at least parts of) your program behind in a very messy state.
A much better way in C++ is to throw an exception which you then catch in main:
#include <stdexcept>
struct fatal_error : std::logic_error {
fatal_error(char const* message) : std::logic_error(message) { }
};
int main() try {
… the normal program flow starts here
} catch (fatal_error const& e) {
std::cerr << e.what() << '\n';
return EXIT_FAILURE;
}
Then, instead of die, you’d simply say throw fatal_error("Something went wrong.");.
Assuming you need these equivalents for debugging purpose...
instead of die() you may invoke the debugger;
instead of var_export() you may inspect your variables content with the debugger.
I wrote a routine to store the backtrace and line no and file name etcetera. The purpose for this was to store such data for whenever an exception is thrown. However, the problem I am facing is that my routine will be called from the catch block and it will end up storing the backtrace up to the catch block. This is not good. I only must add the backtrace till the place where the exception is thrown. I cannot (obviously call it inside the try block since in that case I will end up storing a backtrace even in the cases where no exception is thrown). I could also always store the backtrace to the end of the try block and access it inside the catch block; but there is no way of knowing at which line of the try block the exception will be thrown. Thus the throw function seems to be a good place to add the routine call. But I dont know how to do it. Please help me.
If my strategy seems inherently wrong, please feel free to point me a better solution. If the problem itself is not clear, please leave a comment.
P.S. I wrote the custom exception class to inherit from std::runtime_error.
There is no 'throw function' defined by C++ that you can override. Throwing is handled by the C++ implementation and there's no standard way to insert any kind of code for every throw.
Instead what you can do is make your exception type store the current backtrace when it is constructed.
std::string get_backtrace() {
return "this is the backtrace...";
}
struct backtrace_exception : public std::exception {
std::string b;
backtrace_exception() : b(get_backtrace()) {}
};
int main() {
try {
throw backtrace_exception();
} catch(backtrace_exception &e) {
std::cout << e.b;
}
}
You cannot overload the throw operator. The more usual solution would be to define a macro that packages the exception with a backtrace record. For example this:
#include <string>
#include <iostream>
#include <sstream>
#include <exception>
#include <stdexcept>
#include <type_traits>
template <typename BaseException>
class backtraced_exception : public BaseException {
private:
std::string backtrace;
public:
template <typename... Args>
backtraced_exception(const char* aFilename, int aLineNum, Args&&... args) :
BaseException(std::forward<Args>(args)...) {
std::stringstream ss;
ss << "From '" << aFilename << "' at line " << aLineNum << ":\n"
<< BaseException::what();
backtrace = ss.str();
};
backtraced_exception(const std::exception& e, const char* aFilename, int aLineNum) :
BaseException(static_cast<const BaseException&>(e)) {
std::stringstream ss;
ss << "From '" << aFilename << "' at line " << aLineNum << ":\n"
<< e.what();
backtrace = ss.str();
};
virtual ~backtraced_exception() noexcept { };
virtual const char* what() const noexcept {
return backtrace.c_str();
};
};
#define THROW_WITH_BACKTRACE(EXCEPTION, ARG1) throw backtraced_exception< EXCEPTION >(__FILE__, __LINE__, ARG1)
// ... and you can create more macros for more arguments...
#define CATCH_WITH_BACKTRACE(EXCEPTION, EXCEPT_NAME) catch(backtraced_exception< EXCEPTION >& EXCEPT_NAME)
#define RETHROW_WITH_BACKTRACE(EXCEPT_NAME) throw backtraced_exception< std::decay< decltype(EXCEPT_NAME) >::type >(EXCEPT_NAME, __FILE__, __LINE__)
Use it like this:
int main() {
try {
try {
try {
THROW_WITH_BACKTRACE(std::runtime_error, "This is an example!");
} CATCH_WITH_BACKTRACE(std::runtime_error, e) {
std::cout << "First caught this exception:\n" << e.what() << std::endl;
RETHROW_WITH_BACKTRACE(e);
};
} catch(std::runtime_error& e) { // can also catch normally.
std::cout << "Got this exception:\n"
<< e.what() << std::endl;
// and even rethrow again, with backtrace:
RETHROW_WITH_BACKTRACE(e);
};
} catch(std::runtime_error& e) {
std::cout << "Finally, got this exception:\n"
<< e.what() << std::endl;
};
};
The output is as follows:
First caught this exception:
From 'logged_except.cpp' at line 50:
This is an example!
Got this exception:
From 'logged_except.cpp' at line 53:
From 'logged_except.cpp' at line 50:
This is an example!
Finally, got this exception:
From 'logged_except.cpp' at line 59:
From 'logged_except.cpp' at line 53:
From 'logged_except.cpp' at line 50:
This is an example!
Another good thing with this solution is that you can disable backtracing by simply conditionally defining the macros depending on whether you want backtracing or not (e.g. debug or release build).
The above example requires C++11 features, but you can probably come up with an equivalent solution without those features (i.e., variadic templates, decltype, type-traits, etc.).
And you could also use C++11 exception-pointers to make this scheme even more convenient.
Yeah you can override 'throw' under GCC by overriding this function :
extern "C"
void __cxa_throw (void *thrown_exception, void *pvtinfo, void (*dest)(void *))
After doing your stuff you should call the real 'throw' for that you should use 'dlsym()' under Unix to get its address or use function wrapping under 'mingw' by passing -WL,-wrap,symbole to the linker , like in here GNU gcc/ld - wrapping a call to symbol with caller and callee defined in the same object file , I worked with both methods
For a project, I'd like to use stringstream to carry on data. To achieve this goal, I have to pass some stringstream as parameter to some function, but when I output the stringstreams, I see something like an address.
The code :
#include <iostream>
#include <sstream>
void doStuff(const std::iostream& msg)
{
std::cerr << msg << std::endl;
}
int main(void)
{
doStuff(std::stringstream("av"));
}
The output is :
0xbff4eb40
Can someone explains why I get an address when passing an rvalue ?
And why can't I pass a stringstream by value ?
You probably want to access the string on which the stringstream is storing its data:
void doStuff(const std::stringstream& msg)
{
std::cerr << msg.str() << std::endl;
}
What is happening in your code is that iostreams contain a void* operator which returns 0 if the stream contains any error or has reached EOF, and another value otherwise. This is usefull for error checking.
When you try to write you stream to std::cerr, the compiler realizes that the stream can be converted to a void* using that operator, and that a void* can be written to a ostream(the operator<< has been defined), and therefore uses it.
Note that i changed the method's signature so that it receives an std::stringstream as an argument, since std::iostream::str is not defined(this method is only available on string streams).
You get an address because it (like other streams) has a conversion to void * (which is primarily useful as a Boolean, to see whether reading/writing the stream has failed).
You can't pass it by value, because streams (again, in general, not just stringstreams) don't support copying and/or assigning.
To print the content of the stream, you could do something like:
void dostuff(std::iostream &msg) {
std::cerr << msg.rdbuf() << "\n";
}
Edit: Here's a complete demo program:
#include <iostream>
#include <sstream>
void show(std::ostream &os) {
std::cout << os.rdbuf() << "\n";
}
int main(){
std::stringstream test("whatever");
show(test);
return 0;
}
When I execute it, the output I get is the expected "whatever".
What (if any) are some potential problems with a C++ macro usage like this?
Would an inline function be a more appropriate solution?
#define EVENT_INFO(_format_, ...) CMyEvent::Generate(__FILE__, __LINE__, CMyEvent::EVT_HIGH, _format_, __VA_ARGS__)
void
CMyEvent::Generate(
const char* file, // filename
int line, // line number
CMyEvent::LEVEL level, // severity level
const char *format, // format of the msg / data
...) // variable arguments
{
// Get a message from the pool
CMyEvent* p_msg = GetMessageFromPool();
if(p_msg != NULL)
{
va_list arguments; // points to each unnamed argument
va_start(arguments, format);
// Fill the object with strings and data.
p_msg->Fill(file, line, level, 0, format, arguments);
va_end(arguments);
}
}
As you're using C++, you can avoid the pitfalls of using variable argument lists which are subject to many problems:
No check on quantity of arguments
No check on argument type
To make it more C++, do something like:
#define EVENT_INFO(args) EventLogStream (__FILE__, __LINE__, __PRETTY_FUNCTION__) << args
and invoke it like (warning: all code here is pseudocode and may be syntactically incorrect, but you should get the basic idea):
EVENT_INFO ("The answer to " << the_question << " is " << answer); // usually 42
The EventLogStream is similar to the cout object and like cout, you can provide class specific output:
class Vector3D
{
EventLogStream &operator << (EventLogStream &out) { out << "{" << x << ", " << y << ", " << z << "}"; }
}
If you could rewrite your messaging to use operator<<(), perhaps using std::ostreams with a custom stream buffer, you wouldn't need variable arguments or the ugly (IMHO) macro, and it would look a lot more like C++ than C.
variadic macro is great for use on logging. much better than using iostreams. inline function won't work unless you are willing to pass __FILE__, __LINE__ manually.
You can enclose format with parentheses for safety (not necessary IMHO)
If I generate an exception on my own, I can include any info into the exception: a number of code line and name of source file. Something like this:
throw std::exception("myFile.cpp:255");
But what's with unhandled exceptions or with exceptions that were not generated by me?
A better solution is to use a custom class and a macro. :-)
#include <iostream>
#include <sstream>
#include <stdexcept>
#include <string>
class my_exception : public std::runtime_error {
std::string msg;
public:
my_exception(const std::string &arg, const char *file, int line) :
std::runtime_error(arg) {
std::ostringstream o;
o << file << ":" << line << ": " << arg;
msg = o.str();
}
~my_exception() throw() {}
const char *what() const throw() {
return msg.c_str();
}
};
#define throw_line(arg) throw my_exception(arg, __FILE__, __LINE__);
void f() {
throw_line("Oh no!");
}
int main() {
try {
f();
}
catch (const std::runtime_error &ex) {
std::cout << ex.what() << std::endl;
}
}
It seems everyone is trying to improve your code to throw exceptions in your code, and no one is attempting the actual question you asked.
Which is because it can't be done. If the code that's throwing the exception is only presented in binary form (e.g. in a LIB or DLL file), then the line number is gone, and there's no way to connect the object to to a line in the source code.
There are several possibilities to find out where the exception was thrown:
Using compiler macros
Using __FILE__ and __LINE__ macros at throw location (as already shown by other commenters), either by using them in std exceptions as text, or as separate arguments to a custom exception:
Either use
throw std::runtime_error(msg " at " `__FILE__` ":" `__LINE__`);
or throw
class my_custom_exception {
my_custom_exception(const char* msg, const char* file, unsigned int line)
...
Note that even when compiling for Unicode (in Visual Studio), FILE expands to a single-byte string.
This works in debug and release. Unfortunately, source file names with code throwing exceptions are placed in the output executable.
Stack Walking
Find out exception location by walking the call stack.
On Linux with gcc the functions backtrace() and backtrace_symbols() can get infos about the current call stack. See the gcc documentation how to use them. The code must be compiled with -g, so that debug symbols are placed in the executable.
On Windows, you can walk the stack using the dbghelp library and its function StackWalk64. See Jochen Kalmbach's article on CodeProject for details. This works in debug and release, and you need to ship .pdb files for all modules you want infos about.
You can even combine the two solutions by collecting call stack info when a custom exception is thrown. The call stack can be stored in the exception, just like in .NET or Java. Note that collecting call stack on Win32 is very slow (my latest test showed about 6 collected call stacks per second). If your code throws many exceptions, this approach slows down your program considerably.
No one mentioned boost so far. If you're using boost c++ libraries they do come with some nice exception defaults for this:
#include <boost/exception/diagnostic_information.hpp>
#include <exception>
#include <iostream>
struct MyException : std::exception {};
int main()
{
try
{
BOOST_THROW_EXCEPTION(MyException());
}
catch (MyException &ex)
{
std::cerr << "Unexpected exception, diagnostic information follows:\n"
<< boost::current_exception_diagnostic_information();
}
return 0;
}
And then you might get something like:
Unexpected exception, diagnostic information follows:
main.cpp(10): Throw in function int main()
Dynamic exception type: boost::exception_detail::clone_impl<boost::exception_detail::error_info_injector<MyException> >
std::exception::what: std::exception
Docs: https://www.boost.org/doc/libs/1_63_0/libs/exception/doc/diagnostic_information.html
The simplest solution is to use a macro:
#define throw_line(msg) \
throw std::exception(msg " " __FILE__ ":" __LINE__)
void f() {
throw_line("Oh no!");
}
If you have a debug build and run it in the Visual Studio debugger, then you can break into the debugger when any kind of exception is thrown, before it propagates to the world.
Enable this with the Debug > Exceptions menu alternative and then check-marking the kinds of exceptions that you are interested in.
You can also add the ability to create a dump file, if the application source code is your own. With the dump file and PDB files (symbols) for the specific build, you'll get stacktraces with WinDbg, for example.
Inspired by Frank Krueger's answer and the documentation for std::nested_exception, I realized that you can combine Frank's answer, which I've been using for a while, with std::nested_exception to create a full error stack trace with file & line info. For example with my implementation, running
#include "Thrower.h"
#include <iostream>
// runs the sample function above and prints the caught exception
int main ( )
{
try {
// [Doing important stuff...]
try {
std::string s = "Hello, world!";
try {
int i = std::stoi ( s );
}
catch ( ... ) {
thrower ( "Failed to convert string \"" + s + "\" to an integer!" );
}
}
catch ( Error& e ) {
thrower ( "Failed to [Do important stuff]!" );
}
}
catch ( Error& e ) {
std::cout << Error::getErrorStack ( e );
}
std::cin.get ( );
}
outputs
ERROR: Failed to [Do important stuff]!
# Location:c:\path\main.cpp; line 33
ERROR: Failed to convert string "Hello, world!" to an integer!
# Location:c:\path\main.cpp; line 28
ERROR: invalid stoi argument
Here's my implementation:
#include <sstream>
#include <stdexcept>
#include <regex>
class Error : public std::runtime_error
{
public:
Error ( const std::string &arg, const char *file, int line ) : std::runtime_error( arg )
{
loc = std::string ( file ) + "; line " + std::to_string ( line );
std::ostringstream out;
out << arg << "\n# Location:" << loc;
msg = out.str( );
bareMsg = arg;
}
~Error( ) throw() {}
const char * what( ) const throw()
{
return msg.c_str( );
}
std::string whatBare( ) const throw()
{
return bareMsg;
}
std::string whatLoc ( ) const throw( )
{
return loc;
}
static std::string getErrorStack ( const std::exception& e, unsigned int level = 0)
{
std::string msg = "ERROR: " + std::string(e.what ( ));
std::regex r ( "\n" );
msg = std::regex_replace ( msg, r, "\n"+std::string ( level, ' ' ) );
std::string stackMsg = std::string ( level, ' ' ) + msg + "\n";
try
{
std::rethrow_if_nested ( e );
}
catch ( const std::exception& e )
{
stackMsg += getErrorStack ( e, level + 1 );
}
return stackMsg;
}
private:
std::string msg;
std::string bareMsg;
std::string loc;
};
// (Important modification here)
// the following gives any throw call file and line information.
// throw_with_nested makes it possible to chain thrower calls and get a full error stack traceback
#define thrower(arg) std::throw_with_nested( Error(arg, __FILE__, __LINE__) )
```
I think that a stack trace should get you to the point.
I found 2 solutions, but neither is fully satisfactory:
If you call std::set_terminate, you can from there print the callstack right from the third party exception throw. Unfortunately, there's no way to recover from a terminate handler, and hence your application will die.
If you call std::set_unexpected, then you need to declare as many as possible from your functions with throw(MyControlledException), so that when they throw due to third party called functions, your unexpected_handler will be able to give you a fine-grained idea of where your application threw.
Compile your software in debug mode and run it with valgrind. It is mainly for finding memory leaks but it can also show you the exact line of where exceptions occur valgrind --leak-check=full /path/to/your/software.
Others have already proposed using a macro and possibly a custom class. But in case you have an exception hierarchy, you need to also specify the exception type while throwing:
#define THROW(ExceptionType, message) \
throw ExceptionType(std::string(message) + " in " + __FILE__ + ':' \
+ std::to_string(__LINE__) + ':' + __func__)
THROW(Error, "An error occurred");
The assumption here is that all exceptions accept a single string argument, which is not limiting, as one can convert other arguments to strings (e.g. with std::to_string()) and concatenate them to a single string.
Apart from using a custom class with a macro, as suggested by Frank Krueger, for your own exceptions, you might be interested in taking a look at the structured exception handling mechanism (you're programming under windows, right?)
Check Structured Exception Handling on MSDN