I want to handle errors in my c++ program, so I created some exception classes to manage those errors, but I want to specify at which line in my program the error occurred.
I passed LINE macro to the constructor of my exception class.
For example:
void f(int i){ // LINE A
if(i<0)
throw(OutOfRange("message", __LINE__); // LINE B
}
void main(){
try{
f(-6); // LINE C
}
catch(const OutOfRange& error){
//do something
}
}
In this example I can only get the LINE B number, but I want to get LINE A and LINE C numbers.
Any idea, where and how to use LINE macro ??
Thanks.
You are looking for a stack trace and there's no portable way to get it. Something somewhat similar can be achieved with:
struct SourcePoint
{
const char *filename;
int line;
SourcePoint(const char *filename, int line)
: filename(filename), line(line)
{ }
};
std::vector<SourcePoint> callstack;
struct SourcePointMarker
{
SourcePointMarker(const char *filename, int line)
{
callstack.push_back(SourcePoint(filename, line);
}
~SourcePointMarker()
{
callstack.pop_back();
}
}
#define MARK_FUNCTION \
SourcePointMarker sourcepointmarker(__FILE__, __LINE__);
Then right after the beginning of each function (or point of interest) you just add a line... for example
int myFunction(int x)
{
MARK_FUNCTION
...
}
Using this approach in your error handlers you can know who was called by who and so on (of course you will know only functions or places that have been instrumented with MARK_FUNCTION). If this is needed only during testing (and not in production) then probably you should just enable core dumps and learn how to run a debugger in post-mortem analysis.
You need a stack trace and a debugger. There's no way in Standard C++ that you could find line C without passing it in as an argument (f(-6, __LINE__)), and no way at all that you could find Line A.
Line C would be near impossible (I can't think of a way... except by passing a second argument to f, __LINE__.
Line A as follows:
void f(int i){ const int lineA = __LINE__;
if(i<0)
throw(OutOfRange("message", __LINE__); // LINE B
}
The CPPUNit framework uses macros instead of functions. That way you can easily get the line number at the same place where the macro is called.
I don't think it is a valid approach in a general sense, but you may find it interesting to take a look at the way the CPPUnit developers did it.
In addition to __LINE__, you can also use __func__ and __FILE__ to give you more information.
__func__ will give you line A and you can at least get a line inside the catch-block by rethrowing from there, but I don't know another way to get line C.
It would probably help you to create a backtrace using standard C++11, i.e. cross-platform and without the need for a debugger or cumbersome logging.
In the years since this question was asked, some useful features have been added to C++.
You can trace the call stack that led to an exception using:
std::nested_exception and std::throw_with_nested
It is described on StackOverflow here and here
This will, however, require that you insert try/catch statements at the functions you wish to trace (i.e. functions without this will not appear in your trace).
You could automate this with macros, reducing the amount of code you have to write/change.
Since you can do this with any derived exception class, you can add a lot of information to such a backtrace!
You may also take a look at my MWE on GitHub, where a backtrace would look something like this:
Library API: Exception caught in function 'api_function'
Backtrace:
~/Git/mwe-cpp-exception/src/detail/Library.cpp:17 : library_function failed
~/Git/mwe-cpp-exception/src/detail/Library.cpp:13 : could not open file "nonexistent.txt"
Related
I'd like to use the built-in compiler checks to verify format strings of a custom logging framework to catch the odd runtime crash due to mismatching format string <-> parameters in advance.
Arguments of the custom C++ logging methods are identical to the printf() family so I was attempting to replace all calls to
MyLogger::Error(
with
fprintf(stderr,
Though unfortunately the (clang) preprocessor chokes on the scope resolution operator (::), i.e. instead of ULog::Warn( only the ULog substring is recognized:
#define MyLogger::Error( fprintf(stderr,
Any suggestions on how to make this work much appreciated.
Have you tried a variadic template? found here.
#include <iostream>
namespace MyLogger
{
template <typename... T>
auto Error(const char * _Format, T &&... args)
{
return printf(_Format, std::forward<T>(args)...);
};
}
#define printf(...) MyLogger::Error(__VA_ARGS__)
int main()
{
MyLogger::Error("Non-Macro Print \n");
printf("Macro Print \n");
return 0;
}
Elaborating on the approach suggested by #Someprogrammerdude I've extended the custom logging class to use the clang/gcc format attribute to enable compiler format checking.
The declaration simply becomes
static void Error(const char *format,...) __attribute__ ((format (printf, 1, 2)));
It's even better than the original idea to use the preprocessor to temp. enable checks by replacing calls to the custom formatter with calls to printf() as it's enabled all the time catching argument mismatches immediately!
(FWIW - already fixed dozens of issues and couple potential crashes on our 120+ LOC code base)
What if you modify MyLogger::Error to
MyLogger::Error(args){
if (0) {
fprintf(stderr,args)
}
//actual function
}
This way you get the built-in warnings and it does not effect the efficiency of your code. (You can obviosly actually use the print if you wan to write to stderr, but I think if you wanted that you used that already)
Tried to simplify the situation as much as possible. So I have a class:
class C
{
int * field;
public:
C() : field(nullptr) {}
void init(int* f) { field = f; }
int getI1() { return *field; }
int getI2() { return *field; }
};
which generates 2 Lint warnings 613 (Possible use of null pointer 'C::i'...)
I know that "field" won't be null when getI1() or getI2() are called. And unfortunately I cannot initialize it in constructor. So I want to suppress Lint warnings. I can do it like this
class C
{
int * field;
public:
C() : field(nullptr) {}
void init(int* f) { field = f; }
int getI1() { return *field; } //lint !e613
int getI2() { return *field; } //lint !e613
};
but in my real case:
1) There are rather many such classes and each class has many
functions that use this pointer.
2) My managements doesn't allow me to add too many lint
comments in the code.
So my question: does anyone know a command-line option that will let me tell Lint "I know the code is not best, just stop checking this particular member variable for null"?
Something similar to -sem parameter, maybe?
So my question: does anyone know a command-line option that will let me tell Lint "I know the code is not best, just stop checking this particular member variable for null"?
That's the wrong way to handle it (even if I knew such command line parameter).
PC-Lint warns you correctly about that
int getI1() { return *i; } //lint !e613
int getI2() { return *i; } //lint !e613
may unintentionally dereference a nullptr.
Just trying to suppress1 that waning isn't a very good idea, since the call of the init() function isn't mandatory.
The correct way to get rid of it is to add an explicit check like
int getI1() {
if(i) {
return *i;
}
throw std::runtime_error("i wasn't initialized properly.");
}
1) There are rather many such classes and each class has many functions that use this pointer.
There's no other way than just wading through them and refactor that bad code.
2) My managements doesn't allow me to add too many lint comments in the code.
That's a good policy. They spent the money to install the SCA tool for reasons, and want the code being improved.
If that collides with the time you've got available doing so, ask them to establish a task that allows you to accomplish that.
If you just want to concentrate on other (more important stuff) reported by PC-Lint, use grep or alike tools to filter out what you don't want to see ATM. But don't establish a command line parameters to suppress them completely. That are things that will be forgotten forever and never be touched or approached at later stages again.
1
Suppressing any errors or warnings given by a SCA tool like PC-Lint defeats the whole purpose of it, unless you're absolutely sure the tool gives you a false positive. Otherwise your company could simply save the money spent for the licenses, and stick to the bad coding habits.
It seems that after the constructor has run, you have an instance that is not usable (will crash if you call getT1() or getT2()). That's not something that I like at all.
Much better to have a constructor C(int* f). Problem goes away. This is a case where the warning is entirely justified and warns you of bad code, so the bad code should be fixed.
I know that code is bad, should be fixed and so on. Unfortunately I cannot do it right now (because of huge amount of effort for one person and highly risky changes), but those errors were overwhelming other, sometimes more critical, problems
I found out that to suppress this warning in one line you can do:
-esym(613, C::field)
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 8 years ago.
Improve this question
I'm currently using a C library under C++11, the problem that I'm facing now and I never faced before, it's to handle errors and failures in a way that will be meaningful for the end user of my program.
At the moment in my C++ code there is something as assert(foo()), where foo is a function from this C library and it returns a bool which reflects the state of the operations, true everything is ok, false otherwise.
I'm wondering if there is a better way to handle this, I would like to substitute the default message with some custom error code or a different string/message. Also note that I can't modify this library, so any possible solution needs to take this into account.
The are 2 main points that concern me:
assert is for when I compile my code in debug, I will basically never use assert in production or release mode, nor assert is intended to be used like I'm using it for the moment
a good portion of this functions is highly influenced by user input, so something that works at runtime is highly needed .
What should I do ? I basically have a C function that returns a bool, it doesn't uses any C or C++ specific error handling function or macro, I should wrap it inside a try catch ?
I'm also taking into account the fact that I would like to avoid calling std::abort and I would prefer to clean up everything in case of failure.
I would use C++ exceptions.
You can use some of the already defined standard C++ exception classes, like std::runtime_error, or you can define some custom exception class (derived from e.g. std::runtime_error).
e.g.
// FooWrapper.h -- C++ wrapper around your "foo" library
#pragma once
#include <stdexcept> // For std::runtime_error
#include "foo.h" // The C library header
...
namespace Foo { // Can wrap the raw C library nicely in a namespace
// Custom exception class for your "foo" errors.
class FooError : public std::runtime_error {
public:
explicit FooError(const std::string& errorMessage)
: std::runtime_error(errorMessage) {
// Can do additional initialization stuff, and pass
// additional information regarding the particular "Foo" error,
// e.g. as another constructor parameter.
// ...
}
};
... other stuff in the wrapping header ...
} // namespace Foo
Then, in your C++ code, you can throw the aforementioned exception when foo() function call fails:
if (! foo()) {
throw Foo::FooError("Some information", ...some other error params... );
}
And you can catch that and try to recover or print a nice error message in the GUI part of your code, e.g.:
try {
// ... do something ...
} catch( const Foo::FooError& fooError ) {
// ... try to recover, or display the error message
// returned by fooError.what()
}
Note also that, since the FooError exception class is inserted into the standard C++ exception hierarchy (since it's derived from std::runtime_error), this custom exception can also be caught by C++ code already present in your code base, that tries to catch the more generic std::runtime_error or std::exception classes.
Put all entry points to the library in your code within try/catch blocks as you suggested. Then the quickest and simplest solution is
if (!foo())
throw std::runtime_error("foo(): returned false");
as needed. You can create your own exception class (possibly but not necessarily derived from std::exception when you decide you need more structured behavior, e.g. behavior which depends on exactly which function fails. In the simple case you would just have
try
{
... //The if/throw test will typically not occur here, but deeper within the call stack.
}
catch (std::exception& e)
{
std::cerr << e.what() << std::endl;
//do cleanup
}
or something like that. Edit: As #TNA emphasizes, you put the try/catch block at the point in the code where you are able to handle the error. The if/throw tests can occur anywhere.
If macro and go to statement can be considered, I think this can be an alternative:
#define CHECK (fn) if (!fn) \
{ \
// Set the valid error msg somewhere that can be retrieved later on..
goto QUIT; \
} \
// Usage
AnyObject Afnc()
{
AnyObject anyObj;
CHECK(foo())
QUIT:
return anyObj;
}
I have a logger class. Call it MyLogger. I may use it in a function like this:
void MyFunc(MyLogger& oLogger)
{
//Do stuff
oLogger.Log("In MyFunc : Some Error");
//Do something else
oLogger.Log("In MyFunc : Some other error");
}
Now, I want to prepend "In MyFunc" to the logs if the log comes from inside MyFunc. Similarly for other functions...
Because this is tiresome, I tried something like this:
void MyLogger::PushPrependString(const char*)
{
//Store prepend string in stack and set it as current prepend string.
}
void MyLogger::PopPrependString()
{
//Pop the most recent prepend string.
}
Now, I can use these two functions like this:
void MyFunc(MyLogger& oLogger)
{
oLogger.PushPrependString("In MyFunc : ");
//Do stuff
oLogger.Log("Some Error");
//Do something else
oLogger.Log("Some other error");
oLogger.PopPrependString();
}
The trouble is, if there are multiple returns in a function, this becomes ugly. Is there any way around this? Is this a common problem? Is there any preprocessor macro like __FILE__ or __LINE__ for getting the name of the function a line appears in? Any comments would be appreciated. Thanks.
"The trouble is, if there are multiple returns in a function, this becomes ugly. Is there any way around this?"
Yes, just use an object with constructor (calls PushPrependString) and destructor (calls PopPrependString).
class LogPrefix
{
private:
MyLogger* logger_;
LogPrefix( LogPrefix const& ); // No such.
LogPrefix& operator=( LogPrefix const& ); // No such.
public:
LogPrefix( MyLogger& logger, char const s[] )
: logger_( &logger )
{
logger_->PushPrependString( s );
}
~LogPrefix()
{
logger_->PopPrependString();
}
};
Disclaimer: off the cuff code, not touched by compiler's hands...
"Is this a common problem?"
Yes.
"Is there any preprocessor macro like FILE or LINE for getting the name of the function a line appears in?"
Not in C++98. Various compilers offer various extensions that do that. IIRC C++0x adopts the C99 scheme, which unfortunately just provides static strings.
Cheers & hth.
RAII - Resource Acquisition Is Initialization.
In this case, you create an object on entry to the function that identifies the current function to the logging system; when the function exits (by any return or by exception thrown or by exception not caught), the object will be destroyed, and the destructor changes what is printed in future by the logging system.
In C99, and maybe in some C++ compilers such as G++, there is a predefined variable, __func__ containing the function name. The C++ equivalent is more complex, I believe.
I am writing a library that I would like to be portable. Thus, it should not depend on glibc or Microsoft extensions or anything else that is not in the standard. I have a nice hierarchy of classes derived from std::exception that I use to handle errors in logic and input. Knowing that a particular type of exception was thrown at a particular file and line number is useful, but knowing how the execution got there would be potentially much more valuable, so I have been looking at ways of acquiring the stack trace.
I am aware that this data is available when building against glibc using the functions in execinfo.h (see question 76822) and through the StackWalk interface in Microsoft's C++ implementation (see question 126450), but I would very much like to avoid anything that is not portable.
I was thinking of implementing this functionality myself in this form:
class myException : public std::exception
{
public:
...
void AddCall( std::string s )
{ m_vCallStack.push_back( s ); }
std::string ToStr() const
{
std::string l_sRet = "";
...
l_sRet += "Call stack:\n";
for( int i = 0; i < m_vCallStack.size(); i++ )
l_sRet += " " + m_vCallStack[i] + "\n";
...
return l_sRet;
}
private:
...
std::vector< std::string > m_vCallStack;
};
ret_type some_function( param_1, param_2, param_3 )
{
try
{
...
}
catch( myException e )
{
e.AddCall( "some_function( " + param_1 + ", " + param_2 + ", " + param_3 + " )" );
throw e;
}
}
int main( int argc, char * argv[] )
{
try
{
...
}
catch ( myException e )
{
std::cerr << "Caught exception: \n" << e.ToStr();
return 1;
}
return 0;
}
Is this a terrible idea? It would mean a lot of work adding try/catch blocks to every function, but I can live with that. It would not work when the cause of the exception is memory corruption or lack of memory, but at that point you are pretty much screwed anyway. It may provide misleading information if some functions in the stack do not catch exceptions, add themselves to the list, and rethrow, but I can at least provide a guarantee that all of my library functions do so. Unlike a "real" stack trace I will not get the line number in calling functions, but at least I would have something.
My primary concern is the possibility that this will cause a slowdown even when no exceptions are actually thrown. Do all of these try/catch blocks require an additional set-up and tear-down on each function invocation, or is somehow handled at compile-time? Or are there other issues I have not considered?
I think this is a really bad idea.
Portability is a very worthy goal, but not when it results in a solution that is intrusive, performance-sapping, and an inferior implementation.
Every platform (Windows/Linux/PS2/iPhone/etc) I've worked on has offered a way to walk the stack when an exception occurs and match addresses to function names. Yes, none of these are portable but the reporting framework can be and it usually takes less than a day or two to write a platform-specific version of stack walking code.
Not only is this less time than it'd take creating/maintaining a cross-platform solution, but the results are far better;
No need to modify functions
Traps crashes in standard or third party libraries
No need for a try/catch in every function (slow and memory intensive)
Look up Nested Diagnostic Context once. Here is a little hint:
class NDC {
public:
static NDC* getContextForCurrentThread();
int addEntry(char const* file, unsigned lineNo);
void removeEntry(int key);
void dump(std::ostream& os);
void clear();
};
class Scope {
public:
Scope(char const *file, unsigned lineNo) {
NDC *ctx = NDC::getContextForCurrentThread();
myKey = ctx->addEntry(file,lineNo);
}
~Scope() {
if (!std::uncaught_exception()) {
NDC *ctx = NDC::getContextForCurrentThread();
ctx->removeEntry(myKey);
}
}
private:
int myKey;
};
#define DECLARE_NDC() Scope s__(__FILE__,__LINE__)
void f() {
DECLARE_NDC(); // always declare the scope
// only use try/catch when you want to handle an exception
// and dump the stack
try {
// do stuff in here
} catch (...) {
NDC* ctx = NDC::getContextForCurrentThread();
ctx->dump(std::cerr);
ctx->clear();
}
}
The overhead is in the implementation of the NDC. I was playing with a lazily evaluated version as well as one that only kept a fixed number of entries as well. The key point is that if you use constructors and destructors to handle the stack so that you don't need all of those nasty try/catch blocks and explicit manipulation everywhere.
The only platform specific headache is the getContextForCurrentThread() method. You can use a platform specific implementation using thread local storage to handle the job in most if not all cases.
If you are more performance oriented and live in the world of log files, then change the scope to hold a pointer to the file name and line number and omit the NDC thing altogether:
class Scope {
public:
Scope(char const* f, unsigned l): fileName(f), lineNo(l) {}
~Scope() {
if (std::uncaught_exception()) {
log_error("%s(%u): stack unwind due to exception\n",
fileName, lineNo);
}
}
private:
char const* fileName;
unsigned lineNo;
};
This will give you a nice stack trace in your log file when an exception is thrown. No need for any real stack walking, just a little log message when an exception is being thrown ;)
I don't think there's a "platform independent" way to do this - after all, if there was, there wouldn't be a need for StackWalk or the special gcc stack tracing features you mention.
It would be a bit messy, but the way I would implement this would be to create a class that offers a consistent interface for accessing the stack trace, then have #ifdefs in the implementation that use the appropriate platform-specific methods to actually put the stack trace together.
That way your usage of the class is platform independent, and just that class would need to be modified if you wanted to target some other platform.
In the debugger:
To get the stack trace of where an exception is throw from I just stcik the break point in std::exception constructor.
Thus when the exception is created the debugger stops and you can then see the stack trace at that point. Not perfect but it works most of the time.
Stack managing is one of those simple things that get complicated very quickly. Better leave it for specialized libraries. Have you tried libunwind? Works great and AFAIK it's portable, though I've never tried it on Windows.
This will be slower but looks like it should work.
From what I understand the problem in making a fast, portable, stack trace is that the stack implementation is both OS and CPU specific, so it is implicitly a platform specific problem. An alternative would be to use the MS/glibc functions and to use #ifdef and appropriate preprocessor defines (e.g. _WIN32) to implement the platform specific solutions in different builds.
Since stack usage is highly platform and implementation dependent, there is no way to do it directly that is completely portable. However, you could build a portable interface to a platform and compiler specific implementation, localizing the issues as much as possible. IMHO, this would be your best approach.
The tracer implementation would then link to whatever platform specific helper libraries are available. It would then operate only when an exception occurs, and even then only if you called it from a catch block. Its minimal API would simply return a string containing the whole trace.
Requiring the coder to inject catch and rethrow processing in the call chain has significant runtime costs on some platforms, and imposes a large future maintenance cost.
That said, if you do choose to use the catch/throw mechanism, don't forget that even C++ still has the C preprocessor available, and that the macros __FILE__ and __LINE__ are defined. You can use them to include the source file name and line number in your trace information.