Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Alternative to C++ exception

Tags:

c++

exception

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.

like image 439
Elazar Leibovich Avatar asked Jun 01 '10 13:06

Elazar Leibovich


1 Answers

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.

like image 129
Matthieu M. Avatar answered Oct 07 '22 13:10

Matthieu M.