Elegant way for exiting a function neatly without using goto in C -


we write functions have more 1 exit point (that is, return in c). @ same time, when exiting function, general works such resource cleanup, wish implement them once, rather implementing them @ every exit point. typically, may achieve our wish using goto following:

void f() {     ...     ...{..{... if(exit_cond) goto f_exit; }..}..     ...     f_exit:     general work such cleanup } 

i think using goto here acceptable, , know many people agree on using goto here. just out of curiosity, there exist elegant way neatly exiting function without using goto in c?

why avoid goto?

the problem want solve is: how make sure common code gets executed before function returns caller? issue c programmers, since c not provide built in support raii.

as concede in question body, goto acceptable solution. never-the-less, there may non-technical reasons avoid using it:

  • academic exercise
  • coding standard compliance
  • personal whim (which think motivating question)

there more 1 way skin cat, elegance criteria subjective provide way narrow single best alternative. have decide best option yourself.

explicitly calling cleanup function

if avoiding explicit jump (e.g., goto or break) common cleanup code can encapsulated within function, , explicitly called @ point of return.

int foo () {     ...     if (some_error) {         return foo_cleanup(some_error_code, ...);     }     ... } 

(this similar posted answer, saw after posted, form shown here can take advantage of sibling call optimizations.)

some people feel explicitness more clear, , therefore more elegant. others feel need pass cleanup arguments function major detractor.

add layer of indirection.

without changing semantics of user api, change implementation wrapper composed of 2 parts. part 1 performs actual work of function. part 2 performs cleanup necessary after part 1 done. if each part encapsulated within own function, wrapper function has clean implementation.

struct bar_stuff {...};  static int bar_work (struct bar_stuff *stuff) {     ...     if (some_error) return some_error_code;     ... }  int bar () {     struct bar_stuff stuff = {};     int r = bar_work(&stuff);     return bar_cleanup(r, &stuff); } 

the "implicit" nature of cleanup point of view of function performs work may viewed favorably some. potential code bloat avoided calling cleanup function single place. argue "implicit" behaviors "tricky", , therefore more difficult understand , maintain.

miscellaneous...

more esoteric solutions using setjmp()/longjmp() can considered, using them correctly can difficult. there open-source wrappers implement try/catch exception handling style macros on them (for example, cexcept), have change coding style use style error handling.

one consider implementing function state machine. function tracks progress through each state, error causes function short circuit cleanup state. style reserved particularly complex functions, or functions need retried later , able pick left off.

do romans do.

if need comply coding standards, best approach follow whatever technique prevalent in existing code base. applies aspects of making changes existing stable source code base. considered disruptive introduce new coding style. should seek approval powers if feel change dramatically improve aspect of software. otherwise, "elegance" subjective, arguing sake of "elegance" not going anywhere.


Comments

Popular posts from this blog

javascript - how to protect a flash video from refresh? -

android - Associate same looper with different threads -

visual studio 2010 - Connect to informix database windows form application -