Even though you don't have exceptions, you can build error objects that contain useful information. Just as you can chain exceptions, you can chain error objects so that when this is reported, the developer can see the full range of events along the way that caused the problem (this is assuming that the primary audience for error information is the developer--it usually is).
Each error object should also have __FILE__
and __LINE__
recorded, which is pretty important to knowing exactly what's going on. Also, you can choose whether or not your error object used error codes; error codes are really only required if other code is trying to decide what to do in an error condition. More important to the developer is a text message describing what went wrong, and ideally with what information. Therefore a printf
style constructor of the error object would go a long way.
So, assuming a simple error object implementation:
error_t* foo()
{
int errCode = some_system_call();
if (errCode != OK)
{
return error_object(__FILE__, __LINE__,
"some_system_call() returned %d",
errCode);
}
// continue doing foo stuff
return NULL;
}
and the caller of foo() could return a "chained" error object that allows the developer to track the whole path of the error:
error_t* bar()
{
error_t* errObj = foo();
if (errObj != NULL)
{
return error_object_chain(errObj, __FILE__, __LINE__,
"foo() failed with condition %s",
implicitCondition);
}
return NULL;
}