The reference manual clearly states, " The pointer to the name must be freed by the user after each successful call."
Running under the debugger, I get a backtrace which indicates the segfault was caused by the call to free(); if I run with valgrind, I get the following complaint:
==60068== Invalid free() / delete / delete / realloc()
==60068== at 0x4C2ACDD: free (vg_replace_malloc.c:530)
==60068== by 0x400B35: main (test-get_class_name.c:24)
==60068== Address 0x75a1b00 is 48 bytes inside a block of size 68 alloc'd
==60068== at 0x4C29BE3: malloc (vg_replace_malloc.c:299)
==60068== by 0x5177DCE: H5MM_malloc (H5MM.c:292)
==60068== by 0x51782F0: H5MM_xstrdup (H5MM.c:465)
==60068== by 0x525C982: H5P_get_class_name (H5Pint.c:5033)
==60068== by 0x51FDEF7: H5Pget_class_name (H5P.c:1574)
==60068== by 0x400AF9: main (test-get_class_name.c:21)
==60068== Process terminating with default action of signal 6 (SIGABRT)
==60068== at 0x5F281F7: raise (in /usr/lib64/libc-2.17.so)
==60068== by 0x5F298E7: abort (in /usr/lib64/libc-2.17.so)
==60068== by 0x5F21265: __assert_fail_base (in /usr/lib64/libc-2.17.so)
==60068== by 0x5F21311: __assert_fail (in /usr/lib64/libc-2.17.so)
==60068== by 0x5177BFA: H5MM_final_sanity_check (H5MM.c:232)
==60068== by 0x4E7CF66: H5_term_library (H5.c:403)
==60068== by 0x5F2BA68: __run_exit_handlers (in /usr/lib64/libc-2.17.so)
==60068== by 0x5F2BAB4: exit (in /usr/lib64/libc-2.17.so)
==60068== by 0x5F14C0B: (below main) (in /usr/lib64/libc-2.17.so)
There seem to be three possibilities:
The HDF5 code and documentation are correct, but I’m doing something wrong and/or interpreting the documentation incorrectly.
The HDF5 code is correct, but the documentation is wrong and I should not free the buffer.
The documentation is correct and I should free the buffer, but the HDF5 code is incorrect.
Note that removal of the free() call results in an abort() with the following complaint:
It appears, based on experimentation, that the actual problem is:
Documentation is misleading: despite saying “must be freed by the user,” one must actually call the HDF5 function H5free_memory().
Assuming that this is the correct explanation, can I request that the reference documentation is updated to include an explicit reference to H5free_memory(), instead of leaving the insufficiently hard-bitten user to wrongly infer that they should use the more usual C library function free()?
H5free_memory() is a public API call that was added several years ago. It ensures that the free() call matches the HDF5 library’s re/m/calloc() call. This is mainly of interest to Windows users since the C runtime (CRT) resides in a non-OS, Visual-Studio-specific shared library and i’s very easy to get a mismatch. For example, if you use a release build of the HDF5 library and are building a debug application, the CRTs won’t match and you’ll get memory issues. Ditto if you use a version of HDF5 that was built with Visual Studio 2015 but are building your application with a different version. Unix-y systems generally don’t have this problem unless you are using a specialized memory library.
Note that this is only important when freeing memory that the HDF5 library allocated. Very few HDF5 API calls do this.
Thanks for this, Dana. It appears that in (at least) 1.10.2-snap10, there’s a problem in Linux because for H5Pget_class_name()HDF5 allocates a block of memory with (presumably) malloc() and then hands the user a pointer into the middle of it. An attempt to use free() triggers the checking mechanisms to be found in modern glibc.
My request would be for a tweak to the reference documentation of get_class_name() (and any other user-callable function which returns memory the user must clean up) to state explicitly that it should be cleaned up using H5free_memory() rather than free().