Reputation: 35408
I have a method:
void doSomethingMain(char* s)
{
doSomethingElse(s);
doMoreStuff(s);
}
where the method doSomethingElse()
is like:
void doSomethingElse(char* s)
{
anotherMethod(s);
moreStuff(s);
}
where anotherMethod()
and moreStuff()
call other methods, which on their turn might either go back to doSomethingElse()
or moreStuff()
or other methods... in a very recursive manner, but none of them calls the main doSomethingMain()
method. This is a finite recursion, it will end when the s
is successfully consumed. The methods are void, we cannot change that without a huge effort.
All these methods are consuming the parameter s
and they are checking for errors in s
. What I want to happen is the following: when one of the methods somewhere down the call stack encounters an error in its input parameter (s
) the I want immediately abort the execution of the function that found the error, and jump back to the doMoreStuff()
in the doSomethingMain()
.
Obviously, one of the immediate solutions from a C++
approach is a throw
and a catch()
pair, and from a C
approach is a setjmp
and longjmp
pair... However our unit testing framework does not like the throw
... catch
pairs (it interprets them as errors) and I would like to avoid the longjmp
approach, so here is the question:
What other alternatives do we have in order to interrupt the execution flow of the application in a method and to continue at a specific location (the next statement after the method)?
Upvotes: 1
Views: 391
Reputation: 16441
Yet another approach - use a global error flag.
static int found_error = 0;
void anyFunction(char *s) {
if (found_error) return;
if (something_failed) {
found_error = 1;
return;
}
}
Now, after an error has been detected, some functions will still be called, but will do nothing.
Upvotes: 0
Reputation: 14603
However our unit testing framework does not like the throw ... catch pairs (it interprets them as errors, and no more tests are executed after them)
What about this:
try
{
doMoreStuff(s);
}
catch (...)
{
// hmmm I won't rethrow because my unit testing framework doesn't like it
}
A valid reason for not using exceptions would be, if for some reason, they were disabled (-fno-exceptions
).
Upvotes: 1
Reputation: 497
Best way without jumps or gotos is to check returns and do a do while loop:
void myFunc(char *s) {
bool doneAll = false;
int res = 0;
do {
res = doSomething(s);
if(!res) break;
res = doSomethingElse(s);
if(!res) {
break;
} else {
doneAll = true;
}
while (false); // no really a loop, a smart way of using breaks
// you know can access doneAll to check if everything is done
// Any cleanup here as well
}
Upvotes: 0
Reputation:
This is exactly what longjmp()
is for, sorry. However, you could in theory make all your functions return an error code, then all calls to these functions should be checked for a return code. When an error is encountered, any calling function should return immediately (with the same error code). Thus, one error will result in an immediate return to the first caller (through all other frames on the call stack).
Upvotes: 1
Reputation: 409166
Return an error code, which is checked. You can, for example, return false
(see <stdbool.h>
in C) on error, and true
on success. If a function returns false, then return (possible with
false` as well).
Using setjmp
/longjmp
is not something I would recommend, even for cases like this.
Upvotes: 1
Reputation: 22157
You could change methods to return bool
. If the parsing is successful, at the end of the recursion, return true
which will be passed to the caller function. If parsing at any point proves to be not successful, return false
, and in the caller function test return value of the entire recursion.
However our unit testing framework does not like the throw ... catch pairs (it interprets them as errors, and no more tests are executed after them)
Change your testing unit framework.
Upvotes: 1