When writing a function, my implementation very frequently looks like this:
Call a subfunction
If this subfunction fails to execute (because of an exceptional situation): log this failure and abort the current function
Otherwise continue calling other subfunctions, which in turn can fail
A crucial part is the logging. Every function that fails should add a short description to the log. This way, at the level where the exception is handled, the user can be shown a detailed error message.
For example, consider an application where a new user account can be created, and there is a problem with the database connection. The following inverse stack trace results:
SQLDriverConnect() -> "SQLDriverConnect error: Data source not found and no default driver specified"
OpenDatabaseConnection() -> "Failed to open database connection"
CreateUser() -> "Failed to create the new user"
ValidateAndSaveNewUserAccount() -> "Failed to save the user profile"
Catch the exception and show the logged messages to the user
Using the exceptions feature, I would implement this as follows:
void CreateUser()
{
try {
OpenDatabaseConnection();
}
catch(std::exception& e) {
e.AddLog("Failed to create the new user");
throw;
}
//...
}
Using a simple return value, I'd write the following:
bool CreateUser(Log& log)
{
if (!OpenDatabaseConnection(log))
{
log.Add("Failed to create the new user");
return false;
}
//...
return true;
}
I find both implementations equally good. Therefore, I don't see much advantage in using exceptions. I am well aware that exception handling is generally considered a useful feature, but I don't really understand why. A long time ago, I used exception handling extensively, but I didn't see the big advantage, so now I never use them anymore. Hence my questions:
Using exceptions, how can this be implemented in C++ more concisely?
If not, what is then the advantage of throwing exceptions over returning an "is successful" boolean?
Note: I use the term logging as "collecting an explanation of what went wrong, so it can be presented to the user later on". I'd rather not store that explanation in a global collection of log messages (in memory, in a file or in a database), as it directly describes the specific exception.
Update: Thanks for you responses so far. I understand that exceptions are only useful if the user doesn't need detailed feedback on what went wrong. (Please correct me if I misinterpreted this.)
Your strategy seems to avoid the most useful aspect of exceptions, you can throw an exception class which already has the text of the log information in it - that is generate the text for the log at time the exception is thrown not at the time the exception is caught. Then you don't have to catch at every level going up the stack, but only at the top level.
Thus only one try block, and one log.add - much less code in general.
Something like this seems to remove all your replication.
void OpenDatabaseConnection()
{
if (Error) throw MyException("Failed opening database");
}
void CreateUser()
{
try {
OpenDatabaseConnection();
//...... do everything here
}
catch(MyException& E) { //only one copy of this code
E.AddLog(E.getMessage());
throw;
}
}
If you always want to handle your exceptional conditions immediately after the call, then there is no real advantage.
The advantage comes when you want to handle the condition several layers up the call chain. To do that with your success flag, you'd have to bubble the flag up several layers of subroutine calls. Every layer would have to be written with the knowldege that it has to keep track of the special flag from way down in the bowels of the code. This is just a major primo PITA.
For instance, for realtime work we typically build our applications around an iteration loop. Any error during the loop generally just aborts that iteration of the loop (excepting "fatal" errors, which abort the entire app). The easiest way to handle this is to just throw exceptions from wherever they occur, and handle them all in their own catch blocks at the very outermost of the application.
I think a big case for using exceptions here is that you've now made logging part of your method signatures. In general, I don't think that should be the case, because it's a cross-cutting concern. Imagine trying to do an analogous thing with user permissions, for example. Are you going to write this everywhere?
bool CreateUser(Log& log, UserSecurityContext& u) {
if (!HasPermissionsFor(u, SecurityRoles::AddUser)) {
log.Add("Insufficient permissions");
return false;
}
//...
return true;
}
There are other reasons to want to use exceptions (see Elemental's answer), but anytime the non-use of a language feature impacts the design of your software, it's worth thinking about whether that was the right way to do it.
Exception handling removes error handling from the normal control flow. This way, the code structured more clean. Exception handling also unwinds the stack automatically. This way, you need not to include error handling code in each method called on the way to the error. If you need one of those features, go with exceptions. If you don't, use error-codes or any other method because exceptions have costs (computing time) even if they are not thrown.
Additional answers to your comment. Imagine a code, that calls several functions that may fail.
procedure exceptionTest(...)
{
try
{
call1();
call2();
call3();
call4();
}
catch (...)
{
//errorhandling outside the normal control flow
}
}
without exception:
procedure normalTest(...)
{
if (!call1())
{
//errorHandling1
}
else if (!call2())
{
//errorHandling2
}
else if ....
...
}
As you can easily see, the normal control flow is disrupted with error handling. Compared to this code, the code using exceptions is easier to read.
If you need to add error handling in each method you call, exceptions may not provide benefits. But if you have nested calls that each may generate errors, it may be easier to catch the exception at top level. That's what I meant. It is not the case in your example, still it's good to know where to benefit from exceptions.
Exceptions are using in only extreme situations. Execution of exception is too slow. For log not great errors try use return value.
Example:
int someMethod{
if(erorr_file_not_found){
logger.add("File not found");
return 1;
}
if(error_permission){
logger.add("You have not permissons to write this file");
return 2;
}
return 0;
}
In this case you can print error and process this error on higher level.
Or (more complex):
int someMethod{
int retval=0;
if(someshit){
retval=1;
goto _return;
}
//...
_return:
switch(retval){
case 1:logger.add("Situation 1");break;
case 2:logger.add("Situation 2");break;
//...
}
/*
close files, sockets, etc.
*/
return retval;
}
This way is more hard but most fast.
Depending on your circumstances, you may be able to log from a constructor of your exception (maybe asynchronously) That way your code would look like:
void CreateUser()
{
OpenDatabaseConnection();
}
Of course, you would need to throw your custom exception from OpenDatabaseConnection().
I worked on two projects when this strategy was used with success.
I would propose to separate error handling from logging and from the user interaction.
Every method can write to log files for itself. With a small log message framework, methods can output debug, informational and error message. Depending on the context your applications runs in defined by a config file, e.g., only critical error messages are actually written.
Especially in networking applications, connection failures can always occur and are not exceptional. Use exceptions for unexpected errors that should not occur or that occur only rarely. It can also make sense to use exceptions internally if you need e.g. the stack unrolling feature:
void CreateUser() {
try {
CDatabaseConnection db = ConnectToDatabase();
InsertIntoDB(db, "INSERT INTO ... ");
SetPermission(...);
} catch(...) {}
}
If InsertIntoDB throws an exception because the network connection is lost again, object CDatabaseConnection will be destroyed and SetPermission is never run. Using this can lead to better code.
The third thing you want to do is give the user feedback in an interactive application. That's a whole different thing. Let your internal methods return enumerations of possible error codes eerrorCONNECTIONLOST, eerrorUSERNAMEINVALID, etc Don't return the error strings from core methods. The user interface layer should bother which strings to display (possibly internationalizing them). Internally, the error codes will be much more useful. You could e.g. retry five times if your login method returned eerrorCONNECTIONLOST.
Related
I am currently trying to write a function for a specific type of hardware exception handling.
The program should test, whether a certain condition is true and start a short emergency procedure and finally terminate.
This test will have to be done quite often and should be rather quick.
Further, it is implemented in a project without any further exception handling.
Therefore, putting try statements everywhere is not really an option.
Ideally, such a function would look like this:
void CheckForException(){
if (Condition == true){
cout << "The chosen configuration is very dangerous, do something different!" << endl;
someHardwareFunction();
someStatementEndingTheProgram;
}
}
In principle, I am looking for someStatementEndingTheProgram.
I figured, end(), terminate() and the like are bad style.
Could a throw statement without a try work in this case?
Not answering the title, but the actual problem description: even if putting try's everywhere is not an option, you can wrap the complete code of the main() function in a try block and catch std::exception, so when CheckForException will throw, it will be caught there, so displaying a message and exiting the application can be done easily.
The downside to this approach is that there can be try blocks in your program later on that could catch this exception, so it should be rethrown.
This reeks of bad design in your app.
If you want to prevent the overhead of try-catch but still handle exceptions/error-conditions in a robust way, the code must cater for it: in effect replacing the exception-handling with a custom optimized handler.
In your example you have two basic choices:
if the someStatementEndingTheProgram needs to do cleanup you can call exit() at the exit-point of that function, otherwise just replace it with exit().
redesign your app to handle CheckForException() returning a status, and check that status higher-up the call-chain, e.g.:
int main()
{
bool okay=true;
while (okay)
{
okay=CheckForException();
//other code
}
if (okay) return 0; else return ERROR_CODE;
}
which will let your app terminate normally.
I am writing a C++ code that controls a special device that is the fusion of several SDKs. My code looks like
#define sdk1SafeCall(err) __sdk1SafeCall(err,__FILE__,__LINE__)
int errorcode = 0;
sdk1SafeCall(sdk1_InitializeDevice());
errorcode=sdk2_InitializeDevice();
errorcode=sdk3_InitializeDevice();
if (some_parameter)
{
errorcode=sdk2_readDevice(true);
}
else
{
errorcode=sdk3_writeDevice();
}
label again: errorcode=sdk1_readDevice();
if (error) goto again;
errorcode=close_everything();
Use parameters will rearrange the control flow. My current method uses something like cudaSafeCall to wrap the error codes and exit. What I don't know how to do is where to store detailed explanations of these errors or how to recover from them (such as the goto example). At the end of the day the code looks really messy.
Edit
I do sometimes handle errors with a wrapper.
Writing error-safe code is hard. In your pseudocode, you don't actually deal with errors at all. errorcode will just have the result of "close_everything()" - which may have succeeded, even if everything else went wrong.
The typical way to solve this sort of thing in C++ is to have an object for each "resource" (e.g. a "device"), and throw an exception if something goes wrong that you don't expect to recover from. Wrap the whole function [or an outer set of functions] in a try/catch block.
Of course, if "failure is normal" (e.g. you try to read from a network port, and you get a timeout because there was no data available, that's not something you should throw an exception for). This should use a return-value.
Note that using objects to handle resources requires careful design of the code and especially that your destructor does a good job of cleaning it is run after an exception. Make sure you don't leave things behind if you throw an exception in a constructor - as that is how you get leaks.
There are naturally a whole host of other solutions - after all, we're talking programming, so there's always at least 11 different ways to solve something.
I was told in a comment in another thread that I should be using exceptions whenever anything out of the ordinary happens, even if it isn't fatal to the script. This came up as I was using constructs akin to the following:
return err("File could not be loaded");
which would print the error to the screen, and return false, terminating the instruction processing. It was suggested that this would be better handled with exceptions.
The trouble is that the program is, for all intents and purposes, a language interpreter, controlled through a console, which means that any time a command is input incorrectly, or there is a bug in the interpreted code, an error needs to be displayed.
Besides the fact that these issues seem to minor to be processed as exceptions, how should it be implemented? How can a try block be used to control processing paths? For example, currently my code looks as follows:
if(!validate(code))
return false; //the validate function already having output the error
else
process(code);
How should I ensure that process(code) only executes if validate(code) succeeds? Should I just return false; from the function in the catch block? This would seem to return to the original issue of using return values to handle exceptional events. It seems to me that the fundamental problem is that the issues aren't exceptions at all, but I defer to those with more experience than I.
If an operation may - by design - either succeed or fail, and both of those are common, it might be most clear to structure your command flow in such way that errors are checked "explicitly", like in boolean value of "validate" function.
Exceptions come in handy when you don't want to disturb your regular control flow with error checking and want to move the checking somewhere else, maybe some function call levels above.
Your situation sounds like you don't really need exceptions. If your code looks clean without them, stay with it.
The idea of exceptions is you wouldn't need something like a separate "validate" step. Whenever "process" gets to a point where something's broken, throw an exception.
If you did need a separate validation step for some reason, then it'd look like
validate(code);
process(code);
Validate would throw an exception on failure, in which case process would never be reached.
try
{
validate(code);
process(code);
}
catch(...)
{
return false;
}
return true;
Assuming that validate throws, process won't happen.
Maybe you want your top-level loop to look something like this:
while (!quit) {
try {
process_command_line_input();
}
catch (const std::exception& ex) {
std::cerr << "Error: " << ex.what() << std::endl;
}
}
So, process_command_line_input() gets the next line of input and does whatever it does. If any error is detected, an exception is thrown, the top level loop displays it, and then goes on to the next input line.
The issue is that you have your function set up to use a return code. You can't just drag and drop exceptions in when your code is already set up with return values.
The correct way to do it is like
std::string code;
// input into code
try {
validate(code);
process(code); // Throws an exception.
}
catch(std::runtime_error& except) {
std::cout << except.what();
// recover from here.
}
There is no one correct answer.
It is highly dependent on the code and the situation:
In your situation the simple code above (if it is withing my own class) then error codes are fine:
class MyClass
{
public:
void processesValidCodesOrIgnore(int code)
{
if (validate(code))
{
processesCode(code);
}
}
private:
bool validate(int);
void processesCode(int);
};
As the validate method is private I know its result will always be checked and not ignored so its very easy to just use error codes in this situation.
On the other hand if validate was public I would definately consider using exceptions (depending on usage). As this would force the caller to actively check for problems rather than silently ignoring them.
In C++, RAII is often advocated as a superior approach to exception handling: if an exception is thrown, the stack is unwound, all the destructors are called and resources are cleaned up.
However, this presents a problem with error reporting. Say a very generic function fails, the stack is unwound to the top level and all I see in the logs would be:
Couldn't read from socket: connection reset by peer.
...or any equally generic message. This doesn't say much about the context from which the exception is thrown. Especially if I'm running something like an event queue processing loop.
Of course I could wrap every call to socket reads with a try/catch block, catch the exception, construct a new one with more detailed context information and re-throw it, but it defeats the purpose of having RAII, and is slowly but surely becoming worse than handling return error codes.
What's a better way for detailed for error reporting in standard C++? I'm also open to suggestions involving Boost.
As James McNellis suggested here, there is a really neat trick involving a guard object and the std::uncaught_exception facility.
The idea is to write code like this:
void function(int a, int b)
{
STACK_TRACE("function") << "a: " << a << ", b: " << b;
// do anything
}
And have the message logged only in case an exception is actually thrown.
The class is very simple:
class StackTrace: boost::noncopyable // doesn't make sense to copy it
{
public:
StackTrace(): mStream() {}
~StackTrace()
{
if (std::uncaught_exception())
{
std::cout << mStream.str() << '\n';
}
}
std::ostream& set(char const* function, char const* file, unsigned int line)
{
return mStream << file << "#" << line << " - " << function << " - ";
}
private:
std::ostringstream mStream;
};
#define STACK_TRACE(func) \
StackTrace ReallyUnwieldyName; \
ReallyUnwieldyName.set(func, __FILE__, __LINE__)
One can use __PRETTY_FUNC__ or equivalent to avoid naming the function, but I have found in practice that it was too mangled / verbose for my own taste.
Note that you need a named object if you wish it to live till the end of the scope, which is the purpose here. We could think of tricky ways to generate a unique identifier, but I have never needed it, even when protecting narrower scope within a function, the rules of name hiding play in our favor.
If you combine this with an ExceptionManager (something where exceptions thrown register themselves), then you can get a reference to the latest exception and in case of logging you can rather decide to setup your stack within the exception itself. So that it's printed by what and ignored if the exception is discarded.
This is a matter of taste.
Note that in the presence of ExceptionManager you must remain aware that not all exceptions can be retrieved with it --> only the ones you have crafted yourself. As such you still need a measure of protection against std::out_of_range and 3rd party exceptions.
Say a very generic function fails, the stack is unwound to the top level and all I see in the logs would be [...]
What's a better way for detailed for error reporting in standard C++?
Error handling isn't local to a class or library - it is a application level concern.
Best I can answer you question is that the error reporting should be always implemented by looking first and foremost at the error handling. (And the error handling also including the handling of the error by the user.) Error handling is the decision making about what has to be done about the error.
That is one of the reasons why error reporting is an application level concern and strongly depends on the application workflow. In one application the "connection reset by peer" is a fatal error - in another it is a norm of life, error should be silently handled, connection should be reestablished and pending operation retried.
Thus the approach you mention - catch the exception, construct a new one with more detailed context information and re-throw it - is a valid one too: it is up to the top level application logic (or even user configuration) to decide whether the error is really an error or some special (re)action has to taken upon the condition.
What you have encountered is one of the weaknesses of so called out-of-line error handling (aka exceptions). And I'm not aware of any way to do it better. Exceptions create a secondary code path in the application and if error reporting is vital the design of the secondary code path has to treated just like the main code path.
Obvious alternative to the out-of-line error handling is the in-line error handling - good ol' return codes and log messages on the error conditions. That allows for a trick where application saves all low-severity log messages into internal (circular) buffer (of fixed or configurable size) and dumps them into the log only if high-severity error happens. This way more context information is available and different layers of application do not have to be actively aware of each other. That is also standard (and sometimes literally "standard" - mandated by law) way of error reporting in application fields like safety and mission critical software, were one is not allowed to miss errors.
I've never actually done this, but you could roll your own "stacktrace":
struct ErrorMessage {
const char *s;
ErrorMessage(const char *s) : msg(s) {}
~ErrorMessage() { if (s) std::cout << s << "\n"; }
void done() { s = 0; }
};
void someOperation() {
ErrorMessage msg("Doing the first bit");
// do various stuff that could throw
msg = "Doing the second bit";
// do more stuff that could throw
msg.done();
}
You can have several levels of this (although not necessarily use it at every level):
void handleFoo() {
ErrorMessage msg("Handling foo event");
someOperation();
msg.done();
}
And add more constructors and members:
void handleBar(const BarEvent &b) {
ErrorMessage msg(std::stringstream("Handling bar event ") << b.id);
someOperation();
msg.done();
}
And you needn't write the messages to std::cout. It could be to some logging object, and the object could queue them, and not actually output them to the log unless the catch site tells it to. That way, if you catch an exception that doesn't warrant logging, nothing is written.
It's not pretty, but it's prettier than try/catch/throw or checking return values. And if you forget to call done on success (for example if your function has multiple returns and you miss one), then you will at least see your mistake in the logs, unlike a resource leak.
[Edit: oh, and with a suitable macro you can store __FILE__ and __LINE__ in the ErrorMessage.]
You could add a call stack to your exception. I'm not sure how good this works for release builds but works like a charm with debug. You could do this in the constructor of your exception (to encapsulate it). See here for a starting point. This is possible as well on Linux - eventhough I dont remember how exactly.
I use RAII and exceptions and just have various unit-test-like assert statements throughout the code - if they fail, the the stack unwinds to where I can catch and handle them.
#define APP_ASSERT_MSG(Class,Assertion,szDescription) \
if ( !(Assertion) ) \
{ \
throw Class(__LINE__,__FILE__,szDescription); \
}
For most of my particular use case, all I care about is logging debug information, so my exception has the file and line number in it along with an error message (message is optional as I have an assert without it as well). You could easily add FUNCTION or an error code of some type for better handling.
I can then use it like this:
int nRet = download_file(...);
APP_ASSERT_MSG(DownloadException == ERR_OK, "Download failed");
This makes error handling and reporting much easier.
For really nasty debugging, I used GCC's function instrumentation to keep a trace list of what's going on. It works well, but slows down the app quite a bit.
What I do regularly, FWIW, is not use exceptions, but rather explicit error handling in a standard format (ie: using a macro). For example:
result = DoSomething();
CHECK_RESULT_AND_RETURN_ON_ERROR( result );
Now, obviously, this has many limitations design-wise:
Your return codes may need to be somewhat uniform
Code is cluttered with macros
You may need many macros for various check conditions
The upside, though, is as Dummy00001 said: you can effectively generate a stack trace on demand in the event of a serious error, by simply caching the results. I also use this paradigm to log all unexpected error conditions, so I can adjust the code later to handle unexpected conditions which occur "in the wild".
That's my 2c.
Here's how I handle error reporting in my libraries (this may or may not suit your situation).
First, as part of your design you want a "core" or "system" library that all this common logic will sit in. All you other libraries will then link to the core and use its error reporting APIs, so your whole system has a single compact chunk of logic for handling this mess.
Inside the core, provide a set of logging MACROS such as "LogWarning" and "LogFatal" with documented behavior and expected usage- for example, LogFatal should trigger a hard abort of the process but anything lower than "LogError" is simply advisory (does nothing). The macros can provide a "printf" interface that automatically appends the "LINE", "FILE", and "FUNC" macros as arguments to the underlying singleton object that handles your error reporting.
For the object itself I'll defer to you. However, you want public APIs that configure your "drains"- e.g. log to stderr, log to logfile, log to MS Services log, etc. You also want the underlying singleton to be thread safe, re-entrant where possible, and very robust.
With this system, you can make "exception reporting" ONE MORE DRAIN TYPE. Just add an internal API to that error manager object that packages your logged message as an exception, then throws it. Users can then enable AND DISABLE exceptions-on-error behavior in your code with ONE LINE in their apps. You can put try-catches around 3rd party or system code in you libraries that then calls a "Log..." macro in the catch clauses to enable clean re-throw behavior (with certain platforms and compiler options you can even catch things like segfaults using this).
I'm writing a reactive software, which repeatedly recieves input, processes it and emits relevant output. The main loop looks something like:
initialize();
while (true) {
Message msg,out;
recieve(msg);
process(msg,out);
//no global state is saved between loop iterations!
send(out);
}
I want that whatever error occured during the proccess phase, whetehr it is out of memory error, logical error, invalid assertion etc, the program will clean up whatever it did, and keep running. I'll assume it is invalid input, and simply ignore it.
C++'s exception are exceptionally good for that situation, I could surround process with try/catch clause, and throw exception whenever something goes wrog. The only thing I need to make sure that I clean up all my resources before throwing an exception. This could be verified by RAII, or by writing a global resource allocator (for instance, if your destructor might throw an exception), and use it exclusively for all resources.
Socket s = GlobalResourceHandler.manageSocket(new Socket());
...
try {
process(msg,out);
catch (...) {
GlobalResourceHandler.cleanUp();
}
However, using exception is forbidden in our coding standard (also in Google's C++ standard BTW), as a result all the code is compiled with exceptions off, and I believe nobody's going to change the way everything work just for my design problem.
Also, this is code for embedded platform, so the less C++ extra feature we use, the faster the code becomes, and the more portable it is.
Is there an alternative design I can consider?
update:
I appreciate everyones answer about idiotic code standard. The only thing I can say is, in big organizations you have to have strict and sometimes illogical rules, to make sure no idiot would come and make your good code unmaintainable. The standard is more about people than about technicalities. Yes, bad man can make every code a mess, but it's much worse if you give him extra tools for the task.
I'm still looking for a technical answer.
Coding these kind of services all day long I understand your problem. Although we do have exceptions within our code, we don't return them to the external libraries that invoke it, instead we have a simple 'tribool'.
enum ReturnCode
{
OK = 0, // OK (there is a reason for it to be 0)
KO, // An error occurred, wait for next message
FATAL // A critical error occurred, reboot
};
I must say FATAL is... exceptional. There isn't any code path in the application that returns it, apart from the initialization (can't do much if you're not initialized properly).
C++ here brings much with RAII, since it laughs multiple paths of return off and guarantees deterministic release of the objects it holds.
For the actual code checking, you can simply use some macros:
// Here is the reason for OK being 0 and KO and Fatal being something else
#define CHECK_RETURN(Expr) if (ReturnCode code = (Expr)) return code;
#define CHECK_BREAK(Expr) if (ReturnCode code = (Expr)) \
if (KO == code) break; else return code;
Then you can use them like so:
CHECK_RETURN( initialize() )
while(true)
{
Message msg,out;
CHECK_BREAK( receive(msg) )
CHECK_BREAK( process(msg,out) )
CHECK_BREAK( send(out) )
}
As noted, the real bummer is about constructors. You can't have "normal" constructors with such a situation.
Perhaps can you use boost::optional, if you can't, I would really suggest duplicating the functionality. Combine that with systemic factory functions in lieu of constructors and you're off to go:
boost::optional<MyObject> obj = MyObject::Build(1, 2, 3);
if (!obj) return KO;
obj->foo();
Looks much like a pointer, except that it's stack allocated and thus involves near zero overhead.
If you can't throw an exception, then the alternative is to return (or to return false or similar error code).
Whether you throw or return, you still use C++ deterministic destructors to release resources.
The one thing that you can't easily just 'return' from is a constructor. If you have an unrecoverable error in a constructor, then it's a good time to throw; but if you're not allowed to throw, then instead you must return, and in that case you need some other way to signal construction failure:
Have private constructors and static factory methods; have the factory method return null on construction failure; don't forget to check for a null return when you call a factory method
Have a "get_isConstructedOk()" property which you invoke after each constructor (and don't forget to invoke/check it on every newly-constructed object)
Implement 'two-stage' construction: in which you say that any code which might fail mustn't be in a constructor, and must instead be in a separate bool initialize() method that's called after the constructor (and don't forget to call initialize and don't forget to check its return value).
However, using exception is forbidden
in our coding standard (also in
Google's C++ standard BTW). Is there
an alternative design I can consider?
Short answer is no.
Long answer yes :). You can make all functions return an error code (similar to the implementation of Microsoft's COM platform.
The main disadvantages of this approach are:
you have to handle all exceptional cases explicitly
your code size increases dramatically
the code becomes more difficult to read.
Instead of:
initialize();
while (true) {
Message msg,out;
recieve(msg);
process(msg,out);
//no global state is saved between loop iterations!
send(out);
}
you have:
if( !succeedded( initialize() ) )
return SOME_ERROR;
while (true) {
Message msg,out;
if( !succeeded( RetVal rv = recieve(msg) ) )
{
SomeErrorHandler(rv);
break;
}
if( !succeeded( RetVal rv = process(msg,out) ) )
{
SomeErrorHandler(rv);
break;
}
//no global state is saved between loop iterations!
if( !succeeded( RetVal rv = send(out) ) )
{
SomeErrorHandler(rv);
break;
}
}
furthermore, the implementation all your functions will have to do the same: surround each function call with an if.
In the example above, you also have to decide if the rv value on each iteration constitutes an error for the current function and (eventually) return it directly from the while, or break the while on any error, and return the value.
In short, except for possibly using RAII in your code and templates (are you allowed to use them?), you end up close to "C code, using the C++ compiler".
Your code transforms each function from a two-liner into an eight-liner and so on. You can improve this with use of extra functions and #defined macros but macros have their own idiosyncrasies that you have to be really careful about.
In short, your coding standards are making your code unnecessarily longer, more error prone, harder to understand and more difficult to maintain.
This is a good case to present to whoever is in charge of the coding standards in your company :(
Edit: You can also implement this with signals but they are a bad replacement for exceptions: they do the same thing as exceptions, only they also disable RAII completely and make your code even less elegant and more error prone.
Just because using exceptions is forbidden in your current coding standards this does not mean that you should dismiss them out of hand for future problems you encounter such as this. It may the case that your current coding standards did not envisage such a scenario arising. If they did they would probably give you help as to what the alternative implementation would be.
This sounds to me like a good time to challenge your current coding standards. If the people that wrote them are still there then speak to them directly as they will either be able to answer your question as to alternative strategies or they will accept that this is a valid use-case for exceptions.
However, using exception is forbidden in our coding standard (also in Google's C++ standard BTW). Is there an alternative design I can consider?
Coding standards like that are nuts.
I suggest that you ask the person / people who developed and mandated that standard how to solve your problem. If they have no good answer, use this as justification for ignoring that part of the coding standard ... with your bosses permission of course.
If you are running under windows, you could use SEH exceptions. They also have the advantage of pre-stack-unwind handler which can stop unwind (EXCEPTION_CONTINUE_EXECUTION).
Off the top of my head, you might be able to achieve something similar with signals.
Set up a signal handler to catch appropriate signals and have it clean things up. For example, if your code generates a SIGSEGV as a result of something that would otherwise have thrown an exception a little earlier, you can try catching it with the signal handler.
There may be more to it than this as I have not thought it through.
Hope this helps.
Do you call any libraries that could raise exceptions? If it's the case, you will need a try catch anyway. For your internal errors, each method will need to return an error code (use return only for error code, use reference parameters to return the actual values). If you want to make memory cleanup 100% reliable, you could start your application using a monitor application. If your application crash, the monitor start it again. You still need to close files and DB connection, tho.
Another approach is, instead of throwing exception, set a global error indicator, and return a legal but arbitary input. Then checking in every loop iteration whether or not the global error indicator is set, and if it is - return.
If you're careful enough, you can make sure that returning legal data will never cause you to crash or to cause undefined behaviour. Thus you shouldn't care that the software will keep running a bit until it reaches to the nearest error checking condition.
For example
#define WHILE_R(cond,return_value) while (cond) {\
if (exception_thrown) return return_value
#define ENDWHILE() }
bool isPolyLegal(Poly p) {
PolyIter it(p);
WHILE_R(it.next(),true) //return value is arbitary
...
if (not_enough_memory) exception_thrown = true;
...
ENDWHILE()
}