custom (non-exception) error handling strategy in c++ - c++

What error handling schemes people use in c++ when its necessary, for X or Y reason, to avoid exceptions? I've implemented my own strategy, but i want to know what other people have come up with, and bring discussion on the topic about benefits and drawbacks of each approach
Now, to explain the scheme i'm using on a particular project, it can be summed up like this. Methods that would normally require to throw, implement an interface like:
bool methodName( ...parameters.... , ErrorStack& errStack)
{
if (someError) { errStack.frames.push_back( ErrorFrame( ErrorType , ErrorSource ) );
return false;
}
... normal processing ...
return true;
}
in short, the return parameter says if the processing was ok or an error occurred. the Error Stack is basically a std::vector of error frames that contain detailed information about the error:
enum ErrorCondition {
OK,
StackOverflowInminent,
IndexOutOfBounds,
OutOfMemory
};
struct ErrorFrame {
ErrorCondition condition;
std::string source;
ErrorFrame( ErrorCondition cnd , const char* src ) : condition(cnd) , source(src) {}
inline bool isOK() const {
return OK == condition;
}
};
struct ErrorStack {
std::vector< ErrorFrame > frames;
void clear() {
frames.clear();
}
};
The advantage of this approach is a detailed stack of errors similar to what java exceptions give, but without the runtime overhead of exceptions. The main drawback is that (besides the non-standardness and that i still have to handle exceptions from third-party code somehow and tranlate to an ErrorCondition), is that is hard to mantain the ErrorCondition enum, since multiple components of the source base require different errors, so a second version of this strategy could use a inheritance hierarchy of some sort for the errorConditions, but i'm still not confident about the best way to achieve it

check out http://www.open-std.org/jtc1/sc22/wg21/docs/TR18015.pdf Page 32 onwards

Related

Best practices for using `std::error_code`

I am currently building an embedded system and use a modern C++ compiler.
While I could technically fit exception handling in the given resources (ARM7, more than 10M RAM), I don’t think exceptions are the right tool for something like this and using exceptions requires RTTI, which in turn results in code bloat.
To stay C++-ish anyway I want to use std::error_code (or similar with more data) because I do like the concept.
However, there does not seem to be any consenus on how to actually use them. I have seen at least four different ways of passing them between function calls, two of them with multiple semantics.
Passing by pointer as an argument
void somefunction(Args..., std::error_code* error);
This is the way I have not seen that often and the one I dislike the most. It leaves the return type fully available and (often, but not always) passing nullptr resulted in normal throwing behaviour.
Passing by reference as an argument
void somefunction(Args..., std::error_code& error);
This is the one I prefer. It leaves returnvalue fully available and makes clear that the error_code is not optional.
Returning it by value
std::error_code somefunction(Ret& out <= if used, Args...);
I have seen this one quite often but don’t really like it that much, as it uses up your return value and I generally don’t like “out parameters” unless there’s no way around them.
Returning a std::variant<Ret, std::error_code>
std::variant<Ret, std::error_code> somefunction(Args...);
This one allows for a return value, but makes accessing both value and error harder. Also, it makes code calling the function more verbose.
Semantics
I have seen both way 1 and 2 with different semantics, if the error_code is passed.
Clear at start and set on error
Only set on error
Return right at start if the error_code is “set”
The last way is pretty good if you want to reduce error checking in the calling code. As you can just pass one error_code to multiple functions without checking in between and everything after the first error will not execute, similar to how exceptions would do it.
I personally do prefer way 2 with checking and returning, however I might be biased.
Is there some recommended / generally accepted way to do it?
Ok, this is no complete answer and actually not perfectly on topic because I am not aware of a standard way to do this. But I once saw a nifty little trick to make error codes harder to misuse. Consider the following code:
struct MyEC {
MyEC() {}
MyEC(MyEC && other) : parent(&other) {
// Maybe log and or abort if other is not checked
other.checked = false;
}
// Delete other constructors and assignment operators
~MyEC() {
if(!checked && parent == nullptr) {
// log and or abort
}
}
[[nodiscard]] std::error_code check() {
checked = true;
return ec;
}
void set(std::error_code err) {
if(parent == nullptr) ec = err;
else parent->set(err);
}
private:
MyEC* parent = nullptr;
checked = true;
std::error_code ec {};
};
int foo(MyEC&& err) {
err.set(/* some error */);
return 5;
}
int foo1(MyEC&&) {
return 4;
}
void bar() {
MyEC err;
foo(std::move(err));
// err has the error code and if its not checked, we will know
foo1(std::move(err));
// even though no error occurs, we will abort if err is not checked.
}
It will even then abort, when the error code is not set but also not checked, which is pretty nice. It has a lot of uses after move, which is a bit weird, but this is no problem here.

How would you use Alexandrescu's Expected<T> with void functions?

So I ran across this (IMHO) very nice idea of using a composite structure of a return value and an exception - Expected<T>. It overcomes many shortcomings of the traditional methods of error handling (exceptions, error codes).
See the Andrei Alexandrescu's talk (Systematic Error Handling in C++) and its slides.
The exceptions and error codes have basically the same usage scenarios with functions that return something and the ones that don't. Expected<T>, on the other hand, seems to be targeted only at functions that return values.
So, my questions are:
Have any of you tried Expected<T> in practice?
How would you apply this idiom to functions returning nothing (that is, void functions)?
Update:
I guess I should clarify my question. The Expected<void> specialization makes sense, but I'm more interested in how it would be used - the consistent usage idiom. The implementation itself is secondary (and easy).
For example, Alexandrescu gives this example (a bit edited):
string s = readline();
auto x = parseInt(s).get(); // throw on error
auto y = parseInt(s); // won’t throw
if (!y.valid()) {
// ...
}
This code is "clean" in a way that it just flows naturally. We need the value - we get it. However, with expected<void> one would have to capture the returned variable and perform some operation on it (like .throwIfError() or something), which is not as elegant. And obviously, .get() doesn't make sense with void.
So, what would your code look like if you had another function, say toUpper(s), which modifies the string in-place and has no return value?
Have any of you tried Expected; in practice?
It's quite natural, I used it even before I saw this talk.
How would you apply this idiom to functions returning nothing (that is, void functions)?
The form presented in the slides has some subtle implications:
The exception is bound to the value.
It's ok to handle the exception as you wish.
If the value ignored for some reasons, the exception is suppressed.
This does not hold if you have expected<void>, because since nobody is interested in the void value the exception is always ignored. I would force this as I would force reading from expected<T> in Alexandrescus class, with assertions and an explicit suppress member function. Rethrowing the exception from the destructor is not allowed for good reasons, so it has to be done with assertions.
template <typename T> struct expected;
#ifdef NDEBUG // no asserts
template <> class expected<void> {
std::exception_ptr spam;
public:
template <typename E>
expected(E const& e) : spam(std::make_exception_ptr(e)) {}
expected(expected&& o) : spam(std::move(o.spam)) {}
expected() : spam() {}
bool valid() const { return !spam; }
void get() const { if (!valid()) std::rethrow_exception(spam); }
void suppress() {}
};
#else // with asserts, check if return value is checked
// if all assertions do succeed, the other code is also correct
// note: do NOT write "assert(expected.valid());"
template <> class expected<void> {
std::exception_ptr spam;
mutable std::atomic_bool read; // threadsafe
public:
template <typename E>
expected(E const& e) : spam(std::make_exception_ptr(e)), read(false) {}
expected(expected&& o) : spam(std::move(o.spam)), read(o.read.load()) {}
expected() : spam(), read(false) {}
bool valid() const { read=true; return !spam; }
void get() const { if (!valid()) std::rethrow_exception(spam); }
void suppress() { read=true; }
~expected() { assert(read); }
};
#endif
expected<void> calculate(int i)
{
if (!i) return std::invalid_argument("i must be non-null");
return {};
}
int main()
{
calculate(0).suppress(); // suppressing must be explicit
if (!calculate(1).valid())
return 1;
calculate(5); // assert fails
}
Even though it might appear new for someone focused solely on C-ish languages, to those of us who had a taste of languages supporting sum-types, it's not.
For example, in Haskell you have:
data Maybe a = Nothing | Just a
data Either a b = Left a | Right b
Where the | reads or and the first element (Nothing, Just, Left, Right) is just a "tag". Essentially sum-types are just discriminating unions.
Here, you would have Expected<T> be something like: Either T Exception with a specialization for Expected<void> which is akin to Maybe Exception.
Like Matthieu M. said, this is something relatively new to C++, but nothing new for many functional languages.
I would like to add my 2 cents here: part of the difficulties and differences are can be found, in my opinion, in the "procedural vs. functional" approach. And I would like to use Scala (because I am familiar both with Scala and C++, and I feel it has a facility (Option) which is closer to Expected<T>) to illustrate this distinction.
In Scala you have Option[T], which is either Some(t) or None.
In particular, it is also possible to have Option[Unit], which is morally equivalent to Expected<void>.
In Scala, the usage pattern is very similar and built around 2 functions: isDefined() and get(). But it also have a "map()" function.
I like to think of "map" as the functional equivalent of "isDefined + get":
if (opt.isDefined)
opt.get.doSomething
becomes
val res = opt.map(t => t.doSomething)
"propagating" the option to the result
I think that here, in this functional style of using and composing options, lies the answer to your question:
So, what would your code look like if you had another function, say toUpper(s), which modifies the string in-place and has no return value?
Personally, I would NOT modify the string in place, or at least I will not return nothing. I see Expected<T> as a "functional" concept, that need a functional pattern to work well: toUpper(s) would need to either return a new string, or return itself after modification:
auto s = toUpper(s);
s.get(); ...
or, with a Scala-like map
val finalS = toUpper(s).map(upperS => upperS.someOtherManipulation)
if you don't want to follow a functional route, you can just use isDefined/valid and write your code in a more procedural way:
auto s = toUpper(s);
if (s.valid())
....
If you follow this route (maybe because you need to), there is a "void vs. unit" point to make: historically, void was not considered a type, but "no type" (void foo() was considered alike a Pascal procedure). Unit (as used in functional languages) is more seen as a type meaning "a computation". So returning a Option[Unit] does make more sense, being see as "a computation that optionally did something". And in Expected<void>, void assumes a similar meaning: a computation that, when it does work as intended (where there are no exceptional cases), just ends (returning nothing). At least, IMO!
So, using Expected or Option[Unit] could be seen as computations that maybe produced a result, or maybe not. Chaining them will prove it difficult:
auto c1 = doSomething(s); //do something on s, either succeed or fail
if (c1.valid()) {
auto c2 = doSomethingElse(s); //do something on s, either succeed or fail
if (c2.valid()) {
...
Not very clean.
Map in Scala makes it a little bit cleaner
doSomething(s) //do something on s, either succeed or fail
.map(_ => doSomethingElse(s) //do something on s, either succeed or fail
.map(_ => ...)
Which is better, but still far from ideal. Here, the Maybe monad clearly wins... but that's another story..
I've been pondering the same question since I've watched this video. And so far I didn't find any convincing argument for having Expected, for me it looks ridiculous and against clarity&cleanness. I have come up with the following so far:
Expected is good since it has either value or exceptions, we not forced to use try{}catch() for every function which is throwable. So use it for every throwing function which has return value
Every function that doesn't throw should be marked with noexcept. Every.
Every function that returns nothing and not marked as noexcept should be wrapped by try{}catch{}
If those statements hold then we have self-documented easy to use interfaces with only one drawback: we don't know what exceptions could be thrown without peeking into implementation details.
Expected impose some overheads to the code since if you have some exception in the guts of your class implementation(e.g. deep inside private methods) then you should catch it in your interface method and return Expected. While I think it is quite tolerable for the methods which have a notion for returning something I believe it brings mess and clutter to the methods which by design have no return value. Besides for me it is quite unnatural to return thing from something that is not supposed to return anything.
It should be handled with compiler diagnostics. Many compilers already emit warning diagnostics based on expected usages of certain standard library constructs. They should issue a warning for ignoring an expected<void>.

Is throwing an exception a healthy way to exit?

I have a setup that looks like this.
class Checker
{ // member data
Results m_results; // see below
public:
bool Check();
private:
bool Check1();
bool Check2();
// .. so on
};
Checker is a class that performs lengthy check computations for engineering analysis. Each type of check has a resultant double that the checker stores. (see below)
bool Checker::Check()
{ // initilisations etc.
Check1();
Check2();
// ... so on
}
A typical Check function would look like this:
bool Checker::Check1()
{ double result;
// lots of code
m_results.SetCheck1Result(result);
}
And the results class looks something like this:
class Results
{ double m_check1Result;
double m_check2Result;
// ...
public:
void SetCheck1Result(double d);
double GetOverallResult()
{ return max(m_check1Result, m_check2Result, ...); }
};
Note: all code is oversimplified.
The Checker and Result classes were initially written to perform all checks and return an overall double result. There is now a new requirement where I only need to know if any of the results exceeds 1. If it does, subsequent checks need not be carried out(it's an optimisation). To achieve this, I could either:
Modify every CheckN function to keep check for result and return. The parent Check function would keep checking m_results. OR
In the Results::SetCheckNResults(), throw an exception if the value exceeds 1 and catch it at the end of Checker::Check().
The first is tedious, error prone and sub-optimal because every CheckN function further branches out into sub-checks etc.
The second is non-intrusive and quick. One disadvantage is I can think of is that the Checker code may not necessarily be exception-safe(although there is no other exception being thrown anywhere else). Is there anything else that's obvious that I'm overlooking? What about the cost of throwing exceptions and stack unwinding?
Is there a better 3rd option?
I don't think this is a good idea. Exceptions should be limited to, well, exceptional situations. Yours is a question of normal control flow.
It seems you could very well move all the redundant code dealing with the result out of the checks and into the calling function. The resulting code would be cleaner and probably much easier to understand than non-exceptional exceptions.
Change your CheckX() functions to return the double they produce and leave dealing with the result to the caller. The caller can more easily do this in a way that doesn't involve redundancy.
If you want to be really fancy, put those functions into an array of function pointers and iterate over that. Then the code for dealing with the results would all be in a loop. Something like:
bool Checker::Check()
{
for( std::size_t id=0; idx<sizeof(check_tbl)/sizeof(check_tbl[0]); ++idx ) {
double result = check_tbl[idx]();
if( result > 1 )
return false; // or whichever way your logic is (an enum might be better)
}
return true;
}
Edit: I had overlooked that you need to call any of N SetCheckResultX() functions, too, which would be impossible to incorporate into my sample code. So either you can shoehorn this into an array, too, (change them to SetCheckResult(std::size_t idx, double result)) or you would have to have two function pointers in each table entry:
struct check_tbl_entry {
check_fnc_t checker;
set_result_fnc_t setter;
};
check_tbl_entry check_tbl[] = { { &Checker::Check1, &Checker::SetCheck1Result }
, { &Checker::Check2, &Checker::SetCheck2Result }
// ...
};
bool Checker::Check()
{
for( std::size_t id=0; idx<sizeof(check_tbl)/sizeof(check_tbl[0]); ++idx ) {
double result = check_tbl[idx].checker();
check_tbl[idx].setter(result);
if( result > 1 )
return false; // or whichever way your logic is (an enum might be better)
}
return true;
}
(And, no, I'm not going to attempt to write down the correct syntax for a member function pointer's type. I've always had to look this up and still never ot this right the first time... But I know it's doable.)
Exceptions are meant for cases that shouldn't happen during normal operation. They're hardly non-intrusive; their very nature involves unwinding the call stack, calling destructors all over the place, yanking the control to a whole other section of code, etc. That stuff can be expensive, depending on how much of it you end up doing.
Even if it were free, though, using exceptions as a normal flow control mechanism is a bad idea for one other, very big reason: exceptions aren't meant to be used that way, so people don't use them that way, so they'll be looking at your code and scratching their heads trying to figure out why you're throwing what looks to them like an error. Head-scratching usually means you're doing something more "clever" than you should be.

C++ - Where to throw exception?

I have some kind of an ideological question, so:
Suppose I have some templated function
template <typename Stream>
void Foo(Stream& stream, Object& object) { ... }
which does something with this object and the stream (for example, serializes that object to the stream or something like that).
Let's say I also add some plain wrappers like (and let's say the number of these wrappers equals 2 or 3):
void FooToFile(const std::string& filename, Object& object)
{
std::ifstream stream(filename.c_str());
Foo(stream, object);
}
So, my question is:
Where in this case (ideologically) should I throw the exception if my stream is bad? Should I do this in each wrapper or just move that check to my Foo, so that it's body would look like
if (!foo.good()) throw (something);
// Perform ordinary actions
I understand that this may be not the most important part of coding and these solutions are actually equal, but I just wan't to know "the proper" way to implement this.
Thank you.
In this case it's better to throw it in the lower-level Foo function so that you don't have to copy the validation and exception throwing code in all of your wrappers. In general using exceptions correctly can make your code a lot cleaner by removing a lot of data validation checking that you might otherwise do redundantly at multiple levels in the call stack.
I would prefer not to delay notifying an error. If you know after you have created the stream, that it is no good, why call a method that works on it? I know that to reduce code-redundancy you plan to move it further down. But the downside of that approach is a less-specific error message. So this depends to some extent on the source-code context. If you could get away with a generic error message at the lower-function level you can add the code there, this will surely ease maintanence of the code especially when there are new developers on the team. If you need a specific error message better handle it at the point of failure itself.
To avoid code redundancy call a common function that makes this exception/error for you. Do not copy/paste the code in every wrapper.
The sooner you catch the exceptiont the better. The more specific the exception is - the better. Don't be scared of including most of your code into a try catch blocks, apart fromt he declaration.
For example:
int count = 0;
bool isTrue = false;
MyCustomerObject someObject = null;
try
{
// Initialise count, isTrue, someObject. Process.
}
catch(SpecificException e)
{
// Handle and throw up the stack. You don't want to lose the exception.
}
I like to use helper functions for this:
struct StreamException : std::runtime_error
{
StreamException(const std::string& s) : std::runtime_error(s) { }
virtual ~StreamException() throw() { }
};
void EnsureStreamIsGood(const std::ios& s)
{
if (!s.good()) { throw StreamException(); }
}
void EnsureStreamNotFail(const std::ios& s)
{
if (s.fail()) { throw StreamException(); }
}
I test them immediately before and after performing stream operations if I don't expect a failure.
Traditionally in C++, stream operations don't throw exceptions. This is partly for historic reasons, and partly because streaming failures are expected errors. The way C++ standard stream classes deal with this is to set a flag on a stream to indicate an error has occurred, which user code can check. Not using exceptions makes resumption (which is often required for streaming ops) easier than if exceptions were thrown.

Portable C++ Stack Trace on Exception

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.