views:

530

answers:

4

Hi, 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  A: 

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.

Kevin Gale
+1  A: 

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

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

dfa
Instead of using such frameworks, it is also possible to just use plain goto. Here is an example:#define TRY /*nothing*/#define CATCH(label) label:#define THROW(label) goto labelTRY {fd = open(...);if (fd < 0) THROW(open_failed);...}return;CATCH(open_failed) {...}This does not scale and I would not actually recommend such macros, but the point is that it is possible to use goto for error handling pretty much the same way that you use exceptions, although goto are limited to a single functions so you cannot pass it on to the calling function.
hlovdal
your comment can be entitled "goto considered useful" :)
dfa
Yes ;) In my opinion goto is underused, and I often recommend people to start using it for error handling.
hlovdal
A: 

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...)

LB
A: 

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.

You can call me Chuck