Memory profiling user heap
Memory profiling can use heap management routines on target hardware platforms where there are no or only partial provisions for memory management instructions.
- Situation 1: There are no provisions for malloc, calloc, realloc or free functions on the target platform. The program uses custom heap management routines that may use a user API. Such routines could, for example, be based on a static buffer that performs memory allocation and free functions. In this case, you need to customize the memory heap parameters RTRT_DO_MALLOC and RTRT_DO_FREE in the target deployment port (TDP) to use the custom malloc and free functions. In this case, you can access the custom API functions.
- Situation 2: There are partial implementations of malloc, calloc, realloc or free functions on the target platform, but other functions provide methods of allocating or freeing heap memory. In this case, you do not have access to any custom API. This requires customization of the TDP. Refer to the documentation provided in the target deployment port editor for customization options.
Target deployment port API
void * _PurifyLTHeapAction ( _PurifyLT_API_ACTION, void *, RTRT_U_INT32, RTRT_U_INT8 );
_PurifyLTHeapAction
, the
first parameter is the type of action that will be or has been performed
on the memory block pointed by the second parameter. The following
actions can be used:typedef enum {
_PurifyLT_API_ALLOC,
_PurifyLT_API_BEFORE_REALLOC,
_PurifyLT_API_FREE
} _PurifyLT_API_ACTION;
#define _PurifyLT_NO_DELAYED_FREE 0
#define _PurifyLT_DELAYED_FREE 1
If an allocation or free instruction has a size of 0, this fourth parameter indicates a delayed free in order to detect Late Detect Free Memory Write (FWML ) and Freeing Freed Memory (FFM) errors. See the Build configuration settings section for the memory profiling settings.
A freed delay can only be performed if the block can be freed
with RTRT_DO_FREE
(for the situation 1 described
previously) or ANSI C free
(for situation 2). For
example, if a function requires more parameters than the pointer to
deallocate, then the FMWL and FFM error detection cannot be supported
and FFM errors will be indicated by a Freeing Unallocated Memory (FUM)
error instead.
RTRT_SIZE_T _PurifyLTHeapPtrSize ( void * );
The following
function returns the actual-size of a memory block, depending on the
size requested. Call this function before the actual allocation to
find out the quantity of memory that is available for the block and
the contiguous red zones that are to be monitored by memory profiling.
RTRT_SIZE_T _PurifyLTHeapActualSize ( RTRT_SIZE_T );
Example
my_malloc
, my_realloc
, my_free
and my_msize
demonstrate the four supported memory
heap behaviors. The following routine declares an allocation: void *my_malloc ( int partId, size_t size )
{
void *ret;
size_t actual_size = _PurifyLTHeapActualSize(size);
/* Here is any user code making ret a pointer to a heap or
simulated heap memory block of actual_size bytes */
...
/* Then comes the memory profiling action */
return _PurifyLTHeapAction ( _PurifyLT_API_ALLOC, ret, size, 0 );
/* The user-pointer is returned */
}
In situation 2, where you have access to a custom memory heap API, replace the "..." with the actual malloc API function.
For a my_calloc(size_t nelem, size_t elsize), pass on nelem*elsize as the third parameter of the _PurifyLTHeapAction function. In this case, you might need to replace this operation with a function that takes into account the alignments of elements.
void *my_realloc ( int partId, void * ptr, size_t size )
{
void *ret;
size_t actual_size = _PurifyLTHeapActualSize(size);
/* Before comes first Memory Profiling action */
ret = _PurifyLTHeapAction ( _PurifyLT_API_BEFORE_REALLOC, ptr, size, 0 );
/* ret now contains the actual-pointer */
/* Here is any user code making ret a reallocated pointer to a heap or
simulated heap memory block of actual_size bytes */
...
/* After comes second Memory Profiling action */
return _PurifyLTHeapAction ( _PurifyLT_API_ALLOC, ret, size, 0 );
/* The user-pointer is returned */
}
void my_free ( int partId, void * ptr )
{
/* Memory Profiling action comes first */
void *ret = _PurifyLTHeapAction ( _PurifyLT_API_FREE, ptr, 0, 0 );
/* Any code insuring actual deallocation of ret */
}
void my_free ( int partId, void * ptr )
{
/* Memory Profiling action comes first */
void *ret = _PurifyLTHeapAction ( _PurifyLT_API_FREE, ptr, 0, 1 );
/* Nothing to do here */
}
size_t my_msize ( int partId, void * ptr )
{
return _PurifyLTHeapPtrSize ( ptr );
}
#define _PurifyLT_MALLOC_LIKE(func) \
void *RTRT_CONCAT_MACRO(usr_,func) ( RTRT_SIZE_T size ) \
{ \
void *ret; \
ret = func ( _PurifyLTHeapActualSize ( size ) ); \
return _PurifyLTHeapAction ( _PurifyLT_API_ALLOC, ret, size, 0 ); \
}
#define _PurifyLT_CALLOC_LIKE(func) \
void *RTRT_CONCAT_MACRO(usr_,func) ( RTRT_SIZE_T nelem, RTRT_SIZE_T elsize ) \
{ \
void *ret; \
ret = func ( _PurifyLTHeapActualSize ( nelem * elsize ) ); \
return _PurifyLTHeapAction ( _PurifyLT_API_ALLOC, ret, nelem * elsize, 0 ); \
}
#define _PurifyLT_REALLOC_LIKE(func,delayed_free) \
void *RTRT_CONCAT_MACRO(usr_,func) ( void *ptr, RTRT_SIZE_T size ) \
{ \
void *ret; \
ret = func ( _PurifyLTHeapAction ( _PurifyLT_API_BEFORE_REALLOC, \
ptr, size, delayed_free ), \
_PurifyLTHeapActualSize ( size ) ); \
return _PurifyLTHeapAction ( _PurifyLT_API_ALLOC, ret, size, 0 ); \
}
#define _PurifyLT_FREE_LIKE(func,delayed_free) \
void RTRT_CONCAT_MACRO(usr_,func) ( void *ptr ) \
{ \
if ( delayed_free ) \
{ \
_PurifyLTHeapAction ( _PurifyLT_API_FREE, ptr, 0, delayed_free ); \
} \
else \
{ \
func ( _PurifyLTHeapAction ( _PurifyLT_API_FREE, ptr, 0, delayed_free ) ); \
} \
}