Possibilities to quit a function

In standard C (using setjmp/longjmp) and C++ (using exceptions), it is possible to effectively return to marked points closer to the root of the CFG. In effect, a function may never return, but if it does return, it will be to the point following the call.

However, the low-level nature of the setjmp mechanism actually makes it possible to implement coroutines (albeit in a non-portable way). Posix attempted to improve on this situation by mandating makecontext and friends, which allow for explicit stack swapping, but those functions were deprecated in Posix.1-2001 and removed from Posix.1-2008, citing portability issues, with the suggestion that threads be used instead. Nonetheless, there are a number of coroutine libraries in use which use these features to allow C programmers to enjoy the flexibility of coroutines.

In coroutine control flow, while the execution path following a (co)call might be sinuous, it is still the case that a function call either never returns or eventually returns to the immediately following point. However, the low-level nature of the C library facilities makes it possible to implement more complex control flows, in which a given (co)call might, for example, return several times. (I’ve never seen this particular anomaly implemented in production code, but I can’t claim to have seen even a tiny percentage of all production code in the world 🙂 ).

A gcc extension to C allows for the use of “label values”, which are pointers to labels in the code. These are real values (of type void *) so they can be passed as arguments to functions. (The gcc manual warns against doing this.) With some reverse-engineering, it would probably be possible to write a function which takes one or more label arguments and uses one of them as a return point. That would clearly be a misuse of the feature, would likely not be either portable nor future-proof, and would almost certainly break any coding standards in existence.

The interesting thing about the C library facilities, as opposed to C++ exceptions which are actually part of the core language, is that they really are functions; in C, as with many programming languages, functions can be called indirectly through function pointers so that it might not be readily computable through static analysis which function is being called at a given call site. So, at least in theory, I’d say all bets are off. But in practice it’s probably a safe assumption that a function call will either eventually return to the immediately following point or return to somewhere down the call stack, possibly the operating system environment.

Leave a Comment