Troubleshooting Unexpected Application Behavior During Memory Error Analyses

Symptoms

The application exhibits unexpected behavior, or even crashes, during memory error analyses that include enhanced dangling pointer detection.

Details

Under certain circumstances, enhanced dangling pointer detection may result in failed memory allocation calls that would normally succeed.

Intel Inspector performs dangling pointer detection by intercepting calls to deallocators and deferring the actual deallocation. Ordinarily, when an application frees memory, that memory goes back into the pool of available memory and is often reused by an allocation call soon after it is freed. This makes it difficult to distinguish between a valid use of the new memory block and an invalid attempt to access the memory referred to by the freed block.

Because the Intel Inspector defers deallocation of the memory block, the memory is not immediately returned to the pool of available memory. The block of memory becomes logically invalid to the application because the application freed it. Therefore, if the application subsequently tries to access this memory, the Intel Inspector is certain the access is invalid and reports an error.

In most circumstances, all this behavior is transparent to the application. The operating system uses new blocks of memory to fulfill application requests and everything functions as expected as long as the pool of available memory is large enough to accommodate new allocation requests. The Intel Inspector limits the total size of the memory it holds for dangling pointer detection to maintain this expected behavior.

However, you may encounter situations where the amount of memory available for a specific type of allocation is more limited than the Intel Inspector allows for. For example, if an application repeatedly allocates and frees memory from a fixed size heap, the heap may eventually be entirely consumed and you may see unexpected problems.

Heap Example

void doSomething()
{
    HANDLE fixedHeap = HeapCreate( 0, 0x10000, 0x10000 );
    for ( int i = 0; i < 20; i++ )
    {
        int *p = (int*)HeapAlloc( fixedHeap, HEAP_ZERO_MEMORY, 0x1000 );
        if( p )
            printf( "HeapAlloc succeeded: 0x%p\n", p );
        else
        {
            printf( "HeapAlloc failed\n" );
            break;
        }
        HeapFree( fixedHeap, 0, p );
    }
    HeapDestroy( fixedHeap );
}

This code creates a heap with a fixed size and then loops 20 times allocating and freeing memory from that heap. When run without the Intel Inspector, the call to HeapAlloc is likely to return the same pointer every time through the loop. However, when you run a memory error anaysis, the call to HeapFree is intercepted and the memory is not returned to the heap. Therefore, each iteration through the loop results in a unique pointer, and the call to HeapAlloc fails when i equals 16.

Possible Correction Strategies

Work around the problem by temporarily changing the heap to one that can grow. For example, set the maximum size parameter to 0 when calling HeapCreate.


Supplemental documentation specific to a particular Intel Studio may be available at <install-dir>\<studio>\documentation\ .

For more complete information about compiler optimizations, see our Optimization Notice.