mirror of
https://github.com/HDFGroup/hdf5.git
synced 2025-01-24 15:25:00 +08:00
[svn-r26392] Reinstates r26327-8, which had been reverted due to failures on
Solaris and OS X. Added public API functions that expose the C library's memory allocator for use in filter functions that need to allocate or resize buffers. Intended for use with filter plugins, particularly on Windows, where C runtime (CRT) issues can cause problems. Fixes: HDFFV-9100 Tested on: h5committest + OS X (quail) + Solaris (emu)
This commit is contained in:
parent
63bd09ec8b
commit
2a4ea9b24e
89
src/H5.c
89
src/H5.c
@ -858,29 +858,111 @@ H5close(void)
|
||||
FUNC_LEAVE_API_NOFS(SUCCEED)
|
||||
} /* end H5close() */
|
||||
|
||||
|
||||
/*-------------------------------------------------------------------------
|
||||
* Function: H5allocate_memory
|
||||
*
|
||||
* Purpose: Allocate a memory buffer with the semantics of malloc().
|
||||
*
|
||||
* NOTE: This function is intended for use with filter
|
||||
* plugins so that all allocation and free operations
|
||||
* use the same memory allocator. It is not intended for
|
||||
* use as a general memory allocator in applications.
|
||||
*
|
||||
* Parameters:
|
||||
*
|
||||
* size: The size of the buffer.
|
||||
*
|
||||
* clear: Whether or not to memset the buffer to 0.
|
||||
*
|
||||
* Return:
|
||||
*
|
||||
* Success: A pointer to the allocated buffer.
|
||||
*
|
||||
* Failure: NULL
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
void *
|
||||
H5allocate_memory(size_t size, hbool_t clear)
|
||||
{
|
||||
void *ret_value = NULL;
|
||||
|
||||
FUNC_ENTER_API_NOINIT;
|
||||
H5TRACE2("*x", "zb", size, clear);
|
||||
|
||||
if(clear)
|
||||
ret_value = H5MM_calloc(size);
|
||||
else
|
||||
ret_value = H5MM_malloc(size);
|
||||
|
||||
FUNC_LEAVE_API(ret_value)
|
||||
|
||||
} /* end H5allocate_memory() */
|
||||
|
||||
|
||||
/*-------------------------------------------------------------------------
|
||||
* Function: H5resize_memory
|
||||
*
|
||||
* Purpose: Resize a memory buffer with the semantics of realloc().
|
||||
*
|
||||
* NOTE: This function is intended for use with filter
|
||||
* plugins so that all allocation and free operations
|
||||
* use the same memory allocator. It is not intended for
|
||||
* use as a general memory allocator in applications.
|
||||
*
|
||||
* Parameters:
|
||||
*
|
||||
* mem: The buffer to be resized.
|
||||
*
|
||||
* size: The size of the buffer.
|
||||
*
|
||||
* Return:
|
||||
*
|
||||
* Success: A pointer to the resized buffer.
|
||||
*
|
||||
* Failure: NULL (the input buffer will be unchanged)
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
void *
|
||||
H5resize_memory(void *mem, size_t size)
|
||||
{
|
||||
void *ret_value = NULL;
|
||||
|
||||
FUNC_ENTER_API_NOINIT;
|
||||
H5TRACE2("*x", "*xz", mem, size);
|
||||
|
||||
ret_value = H5MM_realloc(mem, size);
|
||||
|
||||
FUNC_LEAVE_API(ret_value)
|
||||
|
||||
} /* end H5resize_memory() */
|
||||
|
||||
|
||||
/*-------------------------------------------------------------------------
|
||||
* Function: H5free_memory
|
||||
*
|
||||
* Purpose: Frees memory allocated by the library that it is the user's
|
||||
* Purpose: Frees memory allocated by the library that it is the user's
|
||||
* responsibility to free. Ensures that the same library
|
||||
* that was used to allocate the memory frees it. Passing
|
||||
* NULL pointers is allowed.
|
||||
*
|
||||
* Return: SUCCEED/FAIL
|
||||
* Return: SUCCEED/FAIL
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
herr_t
|
||||
H5free_memory(void *mem)
|
||||
{
|
||||
FUNC_ENTER_API_NOINIT
|
||||
FUNC_ENTER_API_NOINIT;
|
||||
H5TRACE1("e", "*x", mem);
|
||||
|
||||
/* At this time, it is impossible for this to fail. */
|
||||
HDfree(mem);
|
||||
|
||||
FUNC_LEAVE_API(SUCCEED)
|
||||
|
||||
} /* end H5free_memory() */
|
||||
|
||||
|
||||
@ -944,3 +1026,4 @@ DllMain(_In_ HINSTANCE hinstDLL, _In_ DWORD fdwReason, _In_ LPVOID lpvReserved)
|
||||
return fOkay;
|
||||
}
|
||||
#endif /* H5_HAVE_WIN32_API && H5_BUILT_AS_DYNAMIC_LIB && H5_HAVE_WIN_THREADS && H5_HAVE_THREADSAFE*/
|
||||
|
||||
|
125
src/H5MM.c
125
src/H5MM.c
@ -31,93 +31,107 @@
|
||||
#include "H5Eprivate.h"
|
||||
#include "H5MMprivate.h"
|
||||
|
||||
#ifndef NDEBUG
|
||||
|
||||
/*-------------------------------------------------------------------------
|
||||
* Function: H5MM_malloc
|
||||
* Function: H5MM_malloc
|
||||
*
|
||||
* Purpose: Just like the POSIX version of malloc(3). This routine
|
||||
* specifically checks for allocations of 0 bytes and fails
|
||||
* in that case. This routine is not called when NDEBUG is
|
||||
* defined.
|
||||
* Purpose: Similar to the C89 version of malloc().
|
||||
*
|
||||
* Return: Success: Ptr to new memory
|
||||
* On size of 0, we return a NULL pointer instead of the
|
||||
* standard-allowed 'special' pointer since that's more
|
||||
* difficult to check as a return value. This is still
|
||||
* considered an error condition since allocations of zero
|
||||
* bytes usually indicate problems.
|
||||
*
|
||||
* Return: Success: Pointer new memory
|
||||
*
|
||||
* Failure: NULL
|
||||
* Failure: NULL
|
||||
*
|
||||
* Programmer: Quincey Koziol
|
||||
* koziol@ncsa.uiuc.edu
|
||||
* Nov 8 2003
|
||||
*
|
||||
* Modifications:
|
||||
* Programmer: Quincey Koziol
|
||||
* Nov 8 2003
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
void *
|
||||
H5MM_malloc(size_t size)
|
||||
{
|
||||
/* Use FUNC_ENTER_NOAPI_NOINIT_NOERR here to avoid performance issues */
|
||||
FUNC_ENTER_NOAPI_NOINIT_NOERR
|
||||
void *ret_value;
|
||||
|
||||
HDassert(size);
|
||||
|
||||
FUNC_LEAVE_NOAPI(HDmalloc(size));
|
||||
/* Use FUNC_ENTER_NOAPI_NOINIT_NOERR here to avoid performance issues */
|
||||
FUNC_ENTER_NOAPI_NOINIT_NOERR
|
||||
|
||||
if(size)
|
||||
ret_value = HDmalloc(size);
|
||||
else
|
||||
ret_value = NULL;
|
||||
|
||||
FUNC_LEAVE_NOAPI(ret_value);
|
||||
} /* end H5MM_malloc() */
|
||||
|
||||
|
||||
/*-------------------------------------------------------------------------
|
||||
* Function: H5MM_calloc
|
||||
* Function: H5MM_calloc
|
||||
*
|
||||
* Purpose: Similar to the POSIX version of calloc(3), except this routine
|
||||
* just takes a 'size' parameter. This routine
|
||||
* specifically checks for allocations of 0 bytes and fails
|
||||
* in that case. This routine is not called when NDEBUG is
|
||||
* defined.
|
||||
* Purpose: Similar to the C89 version of calloc(), except this
|
||||
* routine just takes a 'size' parameter.
|
||||
*
|
||||
* Return: Success: Ptr to new memory
|
||||
* On size of 0, we return a NULL pointer instead of the
|
||||
* standard-allowed 'special' pointer since that's more
|
||||
* difficult to check as a return value. This is still
|
||||
* considered an error condition since allocations of zero
|
||||
* bytes usually indicate problems.
|
||||
*
|
||||
* Failure: NULL
|
||||
*
|
||||
* Return: Success: Pointer new memory
|
||||
*
|
||||
* Failure: NULL
|
||||
*
|
||||
* Programmer: Quincey Koziol
|
||||
* koziol@ncsa.uiuc.edu
|
||||
* Nov 8 2003
|
||||
*
|
||||
* Modifications:
|
||||
* Nov 8 2003
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
void *
|
||||
H5MM_calloc(size_t size)
|
||||
{
|
||||
/* Use FUNC_ENTER_NOAPI_NOINIT_NOERR here to avoid performance issues */
|
||||
FUNC_ENTER_NOAPI_NOINIT_NOERR
|
||||
void *ret_value;
|
||||
|
||||
HDassert(size);
|
||||
|
||||
FUNC_LEAVE_NOAPI(HDcalloc(1,size));
|
||||
/* Use FUNC_ENTER_NOAPI_NOINIT_NOERR here to avoid performance issues */
|
||||
FUNC_ENTER_NOAPI_NOINIT_NOERR
|
||||
|
||||
if(size)
|
||||
ret_value = HDcalloc((size_t)1, size);
|
||||
else
|
||||
ret_value = NULL;
|
||||
|
||||
FUNC_LEAVE_NOAPI(ret_value);
|
||||
} /* end H5MM_calloc() */
|
||||
#endif /* NDEBUG */
|
||||
|
||||
|
||||
/*-------------------------------------------------------------------------
|
||||
* Function: H5MM_realloc
|
||||
* Function: H5MM_realloc
|
||||
*
|
||||
* Purpose: Just like the POSIX version of realloc(3). Specifically, the
|
||||
* following calls are equivalent
|
||||
* Purpose: Similar semantics as C89's realloc(). Specifically, the
|
||||
* following calls are equivalent:
|
||||
*
|
||||
* H5MM_realloc (NULL, size) <==> H5MM_malloc (size)
|
||||
* H5MM_realloc (ptr, 0) <==> H5MM_xfree (ptr)
|
||||
* H5MM_realloc (NULL, 0) <==> NULL
|
||||
* H5MM_realloc(NULL, size) <==> H5MM_malloc(size)
|
||||
* H5MM_realloc(ptr, 0) <==> H5MM_xfree(ptr)
|
||||
* H5MM_realloc(NULL, 0) <==> NULL
|
||||
*
|
||||
* Return: Success: Ptr to new memory or NULL if the memory
|
||||
* was freed or HDrealloc couldn't allocate
|
||||
* memory.
|
||||
* Note that the (NULL, 0) combination is undefined behavior
|
||||
* in the C standard.
|
||||
*
|
||||
* Failure: NULL
|
||||
* Return: Success: Ptr to new memory if size > 0
|
||||
* NULL if size is zero
|
||||
*
|
||||
* Programmer: Robb Matzke
|
||||
* matzke@llnl.gov
|
||||
* Jul 10 1997
|
||||
* Failure: NULL (input buffer is unchanged on failure)
|
||||
*
|
||||
* Programmer: Robb Matzke
|
||||
* Jul 10 1997
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -129,16 +143,19 @@ H5MM_realloc(void *mem, size_t size)
|
||||
/* Use FUNC_ENTER_NOAPI_NOINIT_NOERR here to avoid performance issues */
|
||||
FUNC_ENTER_NOAPI_NOINIT_NOERR
|
||||
|
||||
if(NULL == mem) {
|
||||
if(0 == size)
|
||||
HDassert(mem || size);
|
||||
|
||||
if(NULL == mem && 0 == size) {
|
||||
/* Not defined in the standard, return NULL */
|
||||
ret_value = NULL;
|
||||
}
|
||||
else {
|
||||
ret_value = HDrealloc(mem, size);
|
||||
|
||||
/* Some platforms do not return NULL if size is zero. */
|
||||
if(0 == size)
|
||||
ret_value = NULL;
|
||||
else
|
||||
ret_value = H5MM_malloc(size);
|
||||
} /* end if */
|
||||
else if(0 == size)
|
||||
ret_value = H5MM_xfree(mem);
|
||||
else
|
||||
ret_value = HDrealloc(mem, size);
|
||||
}
|
||||
|
||||
FUNC_LEAVE_NOAPI(ret_value)
|
||||
} /* end H5MM_realloc() */
|
||||
|
@ -33,19 +33,13 @@
|
||||
/* Private headers needed by this file */
|
||||
#include "H5private.h"
|
||||
|
||||
#ifdef NDEBUG
|
||||
#define H5MM_malloc(Z) HDmalloc(Z)
|
||||
#define H5MM_calloc(Z) HDcalloc((size_t)1,Z)
|
||||
#endif /* NDEBUG */
|
||||
#define H5MM_free(Z) HDfree(Z)
|
||||
|
||||
/*
|
||||
* Library prototypes...
|
||||
*/
|
||||
#ifndef NDEBUG
|
||||
H5_DLL void *H5MM_malloc(size_t size);
|
||||
H5_DLL void *H5MM_calloc(size_t size);
|
||||
#endif /* NDEBUG */
|
||||
H5_DLL void *H5MM_realloc(void *mem, size_t size);
|
||||
H5_DLL char *H5MM_xstrdup(const char *s);
|
||||
H5_DLL char *H5MM_strdup(const char *s);
|
||||
|
@ -332,6 +332,8 @@ H5_DLL herr_t H5get_libversion(unsigned *majnum, unsigned *minnum,
|
||||
H5_DLL herr_t H5check_version(unsigned majnum, unsigned minnum,
|
||||
unsigned relnum);
|
||||
H5_DLL herr_t H5free_memory(void *mem);
|
||||
H5_DLL void *H5allocate_memory(size_t size, hbool_t clear);
|
||||
H5_DLL void *H5resize_memory(void *mem, size_t size);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
@ -68,6 +68,18 @@
|
||||
} \
|
||||
}
|
||||
|
||||
#define CHECK_PTR_NULL(ret,where) { \
|
||||
if (VERBOSE_HI) { \
|
||||
print_func(" Call to routine: %15s at line %4d in %s returned %p\n", \
|
||||
(where), (int)__LINE__, __FILE__, (ret)); \
|
||||
} \
|
||||
if (ret) { \
|
||||
TestErrPrintf ("*** UNEXPECTED RETURN from %s is not NULL line %4d in %s\n", \
|
||||
(where), (int)__LINE__, __FILE__); \
|
||||
H5Eprint2(H5E_DEFAULT, stdout); \
|
||||
} \
|
||||
}
|
||||
|
||||
/* Used to make certain a return value _is_ a value */
|
||||
#define VERIFY(_x, _val, where) do { \
|
||||
long __x = (long)_x, __val = (long)_val; \
|
||||
|
68
test/tmisc.c
68
test/tmisc.c
@ -5302,6 +5302,73 @@ test_misc31(void)
|
||||
#endif /* H5_NO_DEPRECATED_SYMBOLS */
|
||||
} /* end test_misc31() */
|
||||
|
||||
|
||||
/****************************************************************
|
||||
*
|
||||
* test_misc32(): Simple test of filter memory allocation
|
||||
* functions.
|
||||
*
|
||||
***************************************************************/
|
||||
static void
|
||||
test_misc32(void)
|
||||
{
|
||||
void *buffer;
|
||||
void *resized;
|
||||
size_t size;
|
||||
|
||||
/* Output message about test being performed */
|
||||
MESSAGE(5, ("Edge case test of filter memory allocation functions\n"));
|
||||
|
||||
/* Test that the filter memory allocation functions behave correctly
|
||||
* at edge cases.
|
||||
*/
|
||||
|
||||
/* FREE */
|
||||
|
||||
/* Test freeing a NULL pointer.
|
||||
* No real confirmation check here, but Valgrind will confirm no
|
||||
* shenanigans.
|
||||
*/
|
||||
buffer = NULL;
|
||||
H5free_memory(buffer);
|
||||
|
||||
/* ALLOCATE */
|
||||
|
||||
/* Size zero returns NULL.
|
||||
* Also checks that a size of zero and setting the buffer clear flag
|
||||
* to TRUE can be used together.
|
||||
*
|
||||
* Note that we have asserts in the code, so only check when NDEBUG
|
||||
* is defined.
|
||||
*/
|
||||
#ifdef NDEBUG
|
||||
buffer = H5allocate_memory(0, FALSE);
|
||||
CHECK_PTR_NULL(buffer, "H5allocate_memory"); /*BAD*/
|
||||
buffer = H5allocate_memory(0, TRUE);
|
||||
CHECK_PTR_NULL(buffer, "H5allocate_memory"); /*BAD*/
|
||||
#endif /* NDEBUG */
|
||||
|
||||
/* RESIZE */
|
||||
|
||||
/* Size zero returns NULL. Valgrind will confirm buffer is freed. */
|
||||
size = 1024;
|
||||
buffer = H5allocate_memory(size, TRUE);
|
||||
resized = H5resize_memory(buffer, 0);
|
||||
CHECK_PTR_NULL(resized, "H5resize_memory");
|
||||
|
||||
/* NULL input pointer returns new buffer */
|
||||
resized = H5resize_memory(NULL, 1024);
|
||||
CHECK_PTR(resized, "H5resize_memory");
|
||||
H5free_memory(resized);
|
||||
|
||||
/* NULL input pointer and size zero returns NULL */
|
||||
#ifdef NDEBUG
|
||||
resized = H5resize_memory(NULL, 0);
|
||||
CHECK_PTR_NULL(resized, "H5resize_memory"); /*BAD*/
|
||||
#endif /* NDEBUG */
|
||||
|
||||
} /* end test_misc32() */
|
||||
|
||||
|
||||
/****************************************************************
|
||||
**
|
||||
@ -5349,6 +5416,7 @@ test_misc(void)
|
||||
test_misc29(); /* Test that speculative metadata reads are handled correctly */
|
||||
test_misc30(); /* Exercise local heap loading bug where free lists were getting dropped */
|
||||
test_misc31(); /* Test Reentering library through deprecated routines after H5close() */
|
||||
test_misc32(); /* Test filter memory allocation functions */
|
||||
|
||||
} /* test_misc() */
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user