* kmp_wrapper_malloc.h -- Wrappers for memory allocation routines
* (malloc(), free(), and others).
*/
#ifndef KMP_WRAPPER_MALLOC_H
#define KMP_WRAPPER_MALLOC_H
1. Declaring standard memory allocation routines in OS-independent way.
2. Passing source location info through memory allocation wrappers.
3. Enabling native memory debugging capabilities.
1. Declaring standard memory allocation routines in OS-independent way.
-----------------------------------------------------------------------
On Linux* OS, alloca() function is declared in <alloca.h> header, while on
Windows* OS there is no <alloca.h> header, function _alloca() (note
underscore!) is declared in <malloc.h>. This header eliminates these
differences, so client code including "kmp_wrapper_malloc.h" can rely on
following routines:
malloc
calloc
realloc
free
alloca
in OS-independent way. It also enables memory tracking capabilities in debug
build. (Currently it is available only on Windows* OS.)
2. Passing source location info through memory allocation wrappers.
-------------------------------------------------------------------
Some tools may help debugging memory errors, for example, report memory
leaks. However, memory allocation wrappers may hinder source location.
For example:
void * aligned_malloc( int size ) {
void * ptr = malloc( size ); // All the memory leaks will be reported at
// this line.
// some adjustments...
return ptr;
};
ptr = aligned_malloc( size ); // Memory leak will *not* be detected here. :-(
To overcome the problem, information about original source location should
be passed through all the memory allocation wrappers, for example:
void * aligned_malloc( int size, char const * file, int line ) {
void * ptr = _malloc_dbg( size, file, line );
// some adjustments...
return ptr;
};
void * ptr = aligned_malloc( size, __FILE__, __LINE__ );
This is a good idea for debug, but passing additional arguments impacts
performance. Disabling extra arguments in release version of the software
introduces too many conditional compilation, which makes code unreadable.
This header defines few macros and functions facilitating it:
void * _aligned_malloc( int size KMP_SRC_LOC_DECL ) {
void * ptr = malloc_src_loc( size KMP_SRC_LOC_PARM );
// some adjustments...
return ptr;
};
#define aligned_malloc( size ) _aligned_malloc( (size) KMP_SRC_LOC_CURR )
// Use macro instead of direct call to function.
void * ptr = aligned_malloc( size ); // Bingo! Memory leak will be
// reported at this line.
3. Enabling native memory debugging capabilities.
-------------------------------------------------
Some platforms may offer memory debugging capabilities. For example, debug
version of Microsoft RTL tracks all memory allocations and can report memory
leaks. This header enables this, and makes report more useful (see "Passing
source location info through memory allocation wrappers").
*/
#include <stdlib.h>
#include "kmp_os.h"
#if KMP_OS_WINDOWS
#include <malloc.h>
#if KMP_MSVC_COMPAT
#define alloca _alloca
#endif
#elif KMP_OS_DRAGONFLY || KMP_OS_FREEBSD || KMP_OS_NETBSD || KMP_OS_OPENBSD
#elif KMP_OS_UNIX
#include <alloca.h>
#else
#error Unknown or unsupported OS.
#endif
function declaration.
KMP_SRC_LOC_PARM -- Source location parameters, to be used to pass
parameters to underlying levels.
KMP_SRC_LOC_CURR -- Source location arguments describing current location,
to be used at top-level.
Typical usage:
void * _aligned_malloc( int size KMP_SRC_LOC_DECL ) {
// Note: Comma is missed before KMP_SRC_LOC_DECL.
KE_TRACE( 25, ( "called from %s:%d\n", KMP_SRC_LOC_PARM ) );
...
}
#define aligned_malloc( size ) _aligned_malloc( (size) KMP_SRC_LOC_CURR )
// Use macro instead of direct call to function -- macro passes info
// about current source location to the func.
*/
#if KMP_DEBUG
#define KMP_SRC_LOC_DECL , char const *_file_, int _line_
#define KMP_SRC_LOC_PARM , _file_, _line_
#define KMP_SRC_LOC_CURR , __FILE__, __LINE__
#else
#define KMP_SRC_LOC_DECL
#define KMP_SRC_LOC_PARM
#define KMP_SRC_LOC_CURR
#endif
with accepts extra arguments (source location info) in debug mode. They
should be used in place of malloc() and free(), this allows enabling native
memory debugging capabilities (if any).
Typical usage:
ptr = malloc_src_loc( size KMP_SRC_LOC_PARM );
// Inside memory allocation wrapper, or
ptr = malloc_src_loc( size KMP_SRC_LOC_CURR );
// Outside of memory allocation wrapper.
*/
#define malloc_src_loc(args) _malloc_src_loc(args)
#define free_src_loc(args) _free_src_loc(args)
1 or 3 parameters, but calls to malloc_src_loc() are always the same:
... malloc_src_loc( size KMP_SRC_LOC_PARM ); // or KMP_SRC_LOC_CURR
Compiler issues warning/error "too few arguments in macro invocation".
Declaring two macros, malloc_src_loc() and _malloc_src_loc(), overcomes the
problem. */
#if KMP_DEBUG
#if KMP_OS_WINDOWS && _DEBUG && !defined(__MINGW32__)
#include <crtdbg.h>
#define KMP_MEM_BLOCK _CLIENT_BLOCK
#define malloc(size) _malloc_dbg((size), KMP_MEM_BLOCK, __FILE__, __LINE__)
#define calloc(num, size) \
_calloc_dbg((num), (size), KMP_MEM_BLOCK, __FILE__, __LINE__)
#define realloc(ptr, size) \
_realloc_dbg((ptr), (size), KMP_MEM_BLOCK, __FILE__, __LINE__)
#define free(ptr) _free_dbg((ptr), KMP_MEM_BLOCK)
#define _malloc_src_loc(size, file, line) \
_malloc_dbg((size), KMP_MEM_BLOCK, (file), (line))
#define _free_src_loc(ptr, file, line) _free_dbg((ptr), KMP_MEM_BLOCK)
#else
#define _malloc_src_loc(size, file, line) malloc((size))
#define _free_src_loc(ptr, file, line) free((ptr))
#endif
#else
#define _malloc_src_loc(size) malloc((size))
#define _free_src_loc(ptr) free((ptr))
#endif
#endif