Visible to Intel only — GUID: GUID-1922CFD8-B776-4AA5-BF73-BFA8634BAC81
Visible to Intel only — GUID: GUID-1922CFD8-B776-4AA5-BF73-BFA8634BAC81
APIs for Custom Memory Allocation
Intel Inspector provides a set of APIs to help it identify the semantics of your malloc-like heap management functions. Annotating your code with these APIs reduces the number of false positives the Intel Inspector reports when analyzing your code.
Usage Tips
Follow these guidelines when using the memory allocation APIs:
Create wrapper functions for your routines, and put the __itt_heap_*_begin and __itt_heap_*_end calls in these functions.
Allocate a unique domain for each pair of allocate/free functions when calling __itt_heap_function_create. This allows the Intel Inspector to verify a matching free function is called for every allocate function call.
Annotate the beginning and end of every allocate function and free function.
Call all function pairs from the same stack frame, otherwise the Intel Inspector assumes an exception occurred and the allocation attempt failed.
Do not call an end function without first calling the matching begin function.
Using Memory Allocation APIs in Your Code
Use This |
To Do This |
---|---|
typedef void* __itt_heap_function; __itt_heap_function __itt_heap_function_create( const __itt_char* name, const __itt_char* domain ); |
Declare a handle type to match begin and end calls and domains.
NOTE:
Parameters of type __itt_char follow the Windows* OS unicode convention. If UNICODE is defined when compiling on a Windows* OS, __itt_char is wchar_t; otherwise it is char. |
void __itt_heap_allocate_begin( __itt_heap_function h, size_t size, int initialized ); void __itt_heap_allocate_end( __itt_heap_function h, void** addr, size_t size, int initialized ); |
Identify allocation functions.
|
void __itt_heap_free_begin( __itt_heap_function h, void* addr ); void __itt_heap_free_end( __itt_heap_function h, void* addr ); |
Identify deallocation functions.
|
void __itt_heap_reallocate_begin( __itt_heap_function h, void* addr, size_t new_size, int initialized ); void __itt_heap_reallocate_end( __itt_heap_function h, void* addr, void** new_addr, size_t new_size, int initialized ); |
Identify reallocation functions. Note that itt_heap_reallocate_end() must be called after the attempt even if no memory is returned. Intel Inspector assumes C-runtime realloc semantics.
|
void __itt_heap_internal_access_begin( void ); void __itt_heap_internal_access_end( void ); |
Identify functions related to private heap management, such as queries for remaining heap size and validation of heap state. This function tells the Intel Inspector that this memory access is intentional and should not be flagged. Call __itt_heap_internal_access_begin() before accessing the underlying heap management internals and __itt_heap_internal_access_end() after the access is finished |
void __itt_heap_record_memory_growth_begin( void ); void __itt_heap_record_memory_growth_end( void ); |
Produce reports of memory growth that occurs between calls to __itt_heap_record_memory_growth_begin() and __itt_heap_record_memory_growth_end() The report identifies any memory allocated but not freed between the two calls. Any memory allocated but not freed prior to the first call to __itt_heap_record_memory_growth_begin() is not reported. Any memory allocated but not freed after the final call to__itt_heap_record_memory_growth_end() is reported when collection is complete. |
Usage Example: Heap Allocation
#include <ittnotify.h> void* user_defined_malloc(size_t size); void user_defined_free(void *p); void* user_defined_realloc(void *p, size_t s); __itt_heap_function my_allocator; __itt_heap_function my_reallocator; __itt_heap_function my_freer; void* my_malloc(size_t s) { void* p; __itt_heap_allocate_begin(my_allocator, s, 0); p = user_defined_malloc(s); __itt_heap_allocate_end(my_allocator, &p, s, 0); return p; } void my_free(void *p) { __itt_heap_free_begin (my_freer, p); user_defined_free(p); __itt_heap_free_end (my_freer, p); } void* my_realloc(void *p, size_t s) { void *np; __itt_heap_reallocate_begin (my_reallocator, p, s, 0); np = user_defined_realloc(p, s); __itt_heap_reallocate_end(my_reallocator, p, &np, s, 0); return(np); } // Make sure to call this init routine before any calls to // user defined allocators. void init_itt_calls() { my_allocator = __itt_heap_function_create("my_malloc", "mydomain"); my_reallocator = __itt_heap_function_create("my_realloc", "mydomain"); my_freer = __itt_heap_function_create("my_free", "mydomain"); } void test_size_of_held_memory(void *p) { size_t s=0; // This will tell Intel Inspector that this memory access // is intentional, and should not be flagged. __itt_heap_internal_access_begin(); #ifdef TARGET_WINDOWS s = _msize(p); #endif __itt_heap_internal_access_end(); } // Now use my_alloc, my_free, my_realloc in place of the user defined // functions.
Usage Example: Heap Growth
#include <ittnotify.h> void ProcessTransaction(TransactionContext x) { ... char* m = (char*) malloc(128); // Memory leak Inspector will report ... return; } // In this example, a leak report will be generated for each transaction in // the for loop. void WaitForTransactions() { ... for (;;) { __itt_heap_record_memory_growth_begin(); TransactionContext x = WaitForTransaction(); // Transaction end-point ProcessTransaction(x); __itt_heap_record_memory_growth_end(); } }
Memory Allocation APIs for On-demand Memory Leak Detection and Memory Growth Detection
These APIs support on-demand memory leak detection and memory growth detection features in the GUI, and analogous memory leak reporting and growth detection capabilities in the CLI.
Mask values can be added or OR’ed together to reset both values with a single call.
Use This in C/C++ Code |
Use This in Fortran Code |
To Do This |
---|---|---|
void __itt_heap_reset_detection( unsigned int mask); |
subroutine itt_heap_reset_detection(mask) integer, intent(in), value:: mask end subroutine itt_heap_reset_detection |
Reset the starting point for on-demand leak detection and/or memory growth reporting. For C/C++, the mask is:
For Fortran, the mask is:
If __itt_heap_record() is called without a prior call to __itt_heap_reset_detection(), the program’s start is used for the starting point. |
void __itt_heap_record(unsigned int mask); |
subroutine itt_heap_record(mask) integer, intent(in), value:: mask end subroutine itt_heap_record |
Record current data about memory leaks and/or memory growth for inclusion in the result. For C/C++, the mask is:
For Fortran, the mask is:
If you are using the GUI for collection, this data is displayed immediately. If you are using the CLI for collection, the data is available after the result is finalized. |
__itt_heap_record_memory_growth_begin() and __itt_heap_record_memory_growth_end() are aliases for __itt_heap_reset_detection(__itt_heap_growth) and __itt_heap_record(__itt_heap_growth), respectively.
Usage Example: On-demand Leak Reporting (C++)
In this example, the goal is to measure the memory leaked by the functions pipeline_stage1() , and pipeline_stage2() . We also want to examine the memory growth exhibited by the function pipeline_stage2() . Strictly speaking, the call to __itt_heap_record() after pipeline_stage1() finishes is not necessary, because any leaks that occur in pipeline stage 1 area also reported by the call to __itt_heap_record() that follows pipeline_stage2(). This example also demonstrates finer-grained leak and growth detection than that available via the CLI and GUI.
#include <ittnotify.h> void ProcessPipeline() { __itt_heap_reset_detection(__itt_heap_leaks); // Start measuring memory leaks here pipeline_stage1(); // Run pipeline stage 1 __itt_heap_record(__itt_heap_leaks); // Report leaks in stage 1 // Now process stage 2 of the pipeline – measure growth and leaks there. // We reset the growth starting point for stage 2. // There’s no need to reset the leak start point, since it follows stage 1. __itt_heap_reset_detection(__itt_heap_growth); // Reset growth starting point for stage 2 pipeline_stage2(); __itt_heap_record(__itt_heap_leaks|__itt_heap_growth);// Report leaks and growth }
Usage Example: On-demand Leak Detection (Fortran)
In this example, the goal is to measure the memory leaked by the functions pipeline_stage1() , and pipeline_stage2() . We also want to examine the memory growth exhibited by the function pipeline_stage2() . Strictly speaking, the call to itt_heap_record() after pipeline_stage1() finishes is not necessary, because any leaks that occur in pipeline stage 1 are also reported by the call toitt_heap_record() that follows pipeline_stage2(). This example also demonstrates finer-grained leak and growth detection than that available via the CLI and GUI.
#include <ittnotify.h> subroutine process_pipeline() ! Start looking for leaks starting with pipeline stage 1. call itt_heap_reset_detection(itt_heap_leaks); pipeline_stage1(); call itt_heap_record(itt_heap_leaks); ! Now process stage 2 of the pipeline – measure growth and leaks there. ! We reset the growth starting point for stage 2. ! There’s no need to reset the leak start point, since it follows stage 1. call itt_heap_reset_baseline(itt_heap_growth); pipeline_stage2(); call itt_heap_record(itt_heap_leaks+itt_heap_growth); }