Re: error handling with HDF5...

Hi Ed,

> Unfortunately, all your example code has little or no error handling
> of HDF function calls. For example, from h5_compound.c:
> 
>     /* 
>      * Create a data type for s3.
>      */
>     s3_tid = H5Tcreate(H5T_COMPOUND, sizeof(float));
> 
>     status = H5Tinsert(s3_tid, "b_name", 0, H5T_NATIVE_FLOAT);
> 
>     /*
>      * Read field b from s1 dataset. Field in the file is found by its name.
>      */
>     status = H5Dread(dataset, s3_tid, H5S_ALL, H5S_ALL, H5P_DEFAULT, s3);
> 
> 
> 
> In this code, the return values are never even checked for anything.
    Yes, we cut it out because it makes the examples hard to read.

> Could you post some HDF5 which has some more complex error handling?
> For example, handling a case of opening a bunch of HDF5 objects,
> handling an error somewhere in the middle of it all, and still closing
> the already opened HDF5 object before exiting the function.
    Unfortunately, our tests don't have really good error recovery, since they
assume that we'll actually fix the code until the test passes.

> Our new programmer, Dan, told me that I shouldn't be using goto in
> C. I decided to ask to see some code from you, rather than launch into
> a long and (believe me) very boring rant about how when I was a boy,
> and gotos were first invented, and 25 cents was a lot of money, blah,
> blah, blah. ;-)
    Well, inside our library we use goto's extensively, but we wrap them inside
macros to hide them from the innocent. :-)
    Here's a chunk of code from inside the library:

hid_t
H5Gcreate(hid_t loc_id, const char *name, size_t size_hint)
{
    H5G_entry_t            *loc = NULL;
    H5G_t                  *grp = NULL;
    hid_t                   ret_value;

    FUNC_ENTER_API(H5Gcreate, FAIL);
    H5TRACE3("i","isz",loc_id,name,size_hint);

    /* Check arguments */
    if (NULL==(loc=H5G_loc (loc_id)))
        HGOTO_ERROR (H5E_ARGS, H5E_BADTYPE, FAIL, "not a location");
    if (!name || !*name)
        HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no name given");
    
    /* Create the group */
    if (NULL == (grp = H5G_create(loc, name, size_hint, H5AC_dxpl_id)))
        HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "unable to create group");
    if ((ret_value = H5I_register(H5I_GROUP, grp)) < 0)
        HGOTO_ERROR(H5E_ATOM, H5E_CANTREGISTER, FAIL, "unable to register 
group");

done:
    if(ret_value<0) {
        if(grp!=NULL)
            H5G_close(grp);
    } /* end if */

    FUNC_LEAVE_API(ret_value);
}

    You can see that we have a single point of entry and exit, which makes the
code "structured".  At the "done:" label, we detect if an error occurred and
unravel the things we allocated at that point.  You can look in the
src/H5Eprivate.h header if you'd like to look at the "HGOTO_ERROR" macros, etc.
    Let me know if that helps...

    Quincey