I\'m working on some code that generates a lot of
ignoring return value of ‘size_t fwrite(const void*, size_t, size_t, FILE*)’, declared with attribute warn
You can remove the warnings like this:
(void) fwrite ( ,,,, );
Addressing your main question, if any of the fwrite() calls fail, I'd guess that it doesn't make sense to continue, as the output is presumably corrupt. In that case, and as you tagged this C++, I'd throw an exception.
Your first solution looks ok. Usually a goto err;
comes in more handy as you may need some common cleanup part (such as rewinding to a known position).
To make GCC quiet just do:
(void)fwrite (&blah, sizeof (blah), 1, fp);
(void)fwrite (&foo, sizeof (foo), 1, fp);
Nesting is bad, and multiple returns are not good either.
I used to use following pattern:
#define SUCCESS (0)
#define FAIL (-1)
int ret = SUCCESS;
if (!fwrite(...))
ret = FAIL;
if (SUCCESS == ret) {
do_something;
do_something_more;
if (!fwrite(...))
ret = FAIL;
}
if (SUCCESS == ret)
do_something;
return ret;
I know it looks ugly but it has single return point, no excessive nesting and very easy to maintain.
Maybe something like this? You catch the errors without making the code too unreadable, and you can do cleanup after the end of the faux loop.
#define WRITE_ERROR 100
#define WRITE_OK 0
int do_fwrite(void* ptr, size_t bytes, int fp) {
if ( fwrite(ptr, bytes, 1, fp) != bytes ) return WRITE_ERROR;
return WRITE_OK;
}
int my_func() {
int errcode = 0;
...
do {
if ( errcode = do_fwrite(&blah, sizeof(blah), fp) ) break;
....
if ( errcode = do_fwrite(&foo, sizeof(foo), fp) ) break;
....
etc
} while( false );
fclose(fp);
return errcode;
}
Something like this would work
if (fwrite (&blah, sizeof (blah), 1, fp) != 1) throw SomeException;
If you're worried about pointers being cleaned up you can wrap the pointer in some form of smart pointer before carrying out your fwrite's.
If you don't want to use smart pointers then this will work, but it's messy, so I'd try the smart pointer route first
if (fwrite (&blah, sizeof (blah), 1, fp) != 1) {
//cleanup here
throw SomeException;
}
Ignoring errors is a bad idea. It's much better to do something nasty like crash the program so that at least you know something went wrong, rather than silently proceeding. Even better is nice error checking and recovery.
If you're using C++, you can create an RAII wrapper for the FILE* so that it'll always get closed. Look at std::auto_ptr for ideas. You can then return a useful error code or from the function whenever you wish, or throw an exception and not have to worry about forgotten cleanup items.