Software Archive
Read-only legacy content
Announcements
FPGA community forums and blogs on community.intel.com are migrating to the new Altera Community and are read-only. For urgent support needs during this transition, please visit the FPGA Design Resources page or contact an Altera Authorized Distributor.
17060 Discussions

deallocate error / heap problem

Intel_C_Intel
Employee
723 Views
My program seems to be getting its heap into a mess, and I've no idea where to look for the culprit. Any suggestions would be much appreciated. The symptoms are as follows:

When I try to deallocate a certain array, it breaks into the debugger with a callstack of

NTDLL! 77f7629c() 
NTDLL! 77f8c4de() 
NTDLL! 77f7e587() 
NTDLL! 77f64f43() 
MSVCRT! 7800113d() 
DFORMD! 003281db() 
DFORMD! 00328250() 
GNR_OPT_END() line 629 + 153 bytes 
GNR_HARNESS() line 574 + 7 bytes 
OPTIMISED! main + 73 bytes 
mainCRTStartup() line 338 + 17 bytes 
KERNEL32! 77f1ba06() 


In the debug output window, I get
HEAP[optimiseD.exe]: Invalid Address specified to RtlFreeHeap( ae0000, ffbda8 )


When I list the contents of the array I'm just trying to dispose of, the first 75 elements are ok, then the rest display as 'Undefined Address' in the watch window.

If I single-step up to this point, the array is completely fine until I deallocate another array in the line before. When this happens, the entries in the problem array change to 'Undefined Address'.

Ok, now what? Is there some way I can check the integrity of the heap, and find out at what point in my code (very long) it is getting corrupted? Or can you suggest anything else?

Thanks

Ian
0 Kudos
5 Replies
Steven_L_Intel1
Employee
723 Views
The symptoms suggest you are corrupting the descriptor for the allocatable variable, perhaps by an out-of-bounds array reference. Are you using POINTER or ALLOCATABLE? Perhaps the array you're deallocating first overlaps the second array?

Steve
0 Kudos
Intel_C_Intel
Employee
723 Views
It's a pointer, as it exists within a user-defined type:

    type retrain_data 
        character(19) :: cTimeStamp = 'none' 
        real(8), pointer :: dX(:, :) => null() 
        real(8), pointer :: dYactual(:) => null() 
        real(8), pointer :: dYpred(:) => null() 
    end type retrain_data


I have two allocatable arrays sRetrain(:) and sRetrainCopy(:) of the type described above and it is when I deallocate sRetrain(1)%dX that I get the corruption in sRetrainCopy(1)%dX. I'll have a look for array overruns, but I had hoped that the array bounds checking would find these automatically.

What I was really wondering is whether I can use _CrtCheckMemory() and related functions from the C runtime library to help diagnose this? I tried yesterday and couldn't work out how to link the necessary routines in. I don't know if they'd work with CVF allocate() in any case, even if I do tell it to use the debug libraries.
0 Kudos
Intel_C_Intel
Employee
723 Views
Ok, I blame the fortran standard. 8-)

sRetrainCopy(i) = sRetrain(i)

is equivalent to
sRetrainCopy(i)%cTimeStamp = sRetrain(i)%cTimeStamp  
sRetrainCopy(i)%dX => sRetrain(i)%dX  
sRetrainCopy(i)%dYactual => sRetrain(i)%dYactual  
sRetrainCopy(i)%dyPred => sRetrain(i)%dYpred


So do copy the actual array values (rather than do pointer assignment), I need to copy each member of the type explicitly:
sRetrainCopy(i)%cTimeStamp = sRetrain(i)%cTimeStamp  
sRetrainCopy(i)%dX = sRetrain(i)%dX  
etc.

I'd still like to know whether _CrtCheckMemory() can be used though.

Ian
0 Kudos
Steven_L_Intel1
Employee
723 Views
I don't think you can use the crt routine for this purpose. We do many allocations using direct Win32 API calls rather than malloc.

Steve
0 Kudos
Intel_C_Intel
Employee
723 Views
Of course you need to allocate memory to your pointers before you do the deep copies. Also, if you are using pointer components only because CVF doesn't yet support TR 15581, so your pointer components will necessarily be the only handles to what they point at, you also most likely want to check to see if they are associated with something and deallocate them to avoid memory leaks before allocating memory to them or skip the deallocate/allocate steps entirely if they already point at something that is the right shape. I usually write an elemental subroutine to do all this stuff and overload assignment(=) with it so that assignments to arrays of the user-defined type work the way I want it to. Of course, if you don't want assignment to be so consistent (e.g. sometimes you don't want deep copies or you want to retain previous targets) this might not be a good idea.
0 Kudos
Reply