Using callback functions for error handling in C

2019-04-12 22:45发布

问题:

I have been thinking about the difficulty incurred with C error handling.. like who actually does

if(printf("hello world")==-1){exit(1);}

But you break common standards by not doing such verbose, and usually useless coding. Well what if you had a wrapper around the libc? like so you could do something like..

//main...
error_catchall(my_errors);
printf("hello world"); //this will automatically call my_errors on an error of printf
ignore=1; //this makes it so the function will return like normal and we can check error values ourself
if(fopen.... //we want to know if the file opened or not and handle it ourself.
}

int my_errors(){
   if(ignore==0){
      _exit(1); //exit if we aren't handling this error by flagging ignore
   }
return 0;
//this is called when there is an error anywhere in the libc
}
...

I am considering making such a wrapper as I am synthesizing my own BSD licensed libc(so I already have to touch the untouchable..), but I would like to know what people think about it.. would this actually work in real life and be more useful than returning -1?

回答1:

But how would you be able to catch the error when it was expected? For example I might expect a file open to fail and want to deal with it in code instead of the generic error catcher.

To do this you would need two versions of every function. One that trapped errors and one the returns errors.

I did something like this long ago without modifying the library. I just created wrapper functions for common calls that did error checking. So my errchk_malloc call checked the return and raised an error if the allocation failed. Then I just used this version everywhere in place of the built in malloc.



回答2:

during this years I've seen several attempts to mimics try/catch in ANSI C:

  • http://simgrid.gforge.inria.fr/doc/group__XBT__ex.html
  • http://llg.cubic.org/trycatch/

I think that try/catch approach is more simple than your.



回答3:

if the goal is to exit cleanly as soon as you encounter an error that's ok... but if you want to do a minimum of error recovery, i can't see how your approach is useful...

To avoid this kind of problem, I sometimes use LD_PRELOAD_PATH to integrate my error management (only for my own projects since this is not a really good practice...)



回答4:

Do you really want to change the standard behaviors of your LIBC ? You could add a few extensions around common functions.

For example, Gnome uses g_malloc and g_try_malloc. The former will abort on failure while the later will simply yield a null-pointer like malloc.