- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Weuse array reallocation a lot in our code, as the data models grow. In this particular instance the model is big (though not as big as some I have seen) andone particular program runs for some 5+ hours before it dies with the following error :
[cpp]HEAP[viewer.exe]: Heap block at 05B24F48 modified at 05B252C4 past requested size of 374 Windows has triggered a breakpoint in viewer.exe. This may be due to a corruption of the heap, and indicates a bug in viewer.exe or any of the DLLs it has loaded. The output window may have more diagnostic information HEAP[viewer.exe]: Invalid address specified to RtlFreeHeap( 03A20000, 05B24F50 ) Windows has triggered a breakpoint in viewer.exe.[/cpp]
The code in question below shows the arrays are initially allocatedsize 200 and when reallocated are increased by 20
[cpp] module M_viewer implicit none !------------------------------------------------ ! Module for viewer !------------------------------------------------ integer*4 :: G_ncurrent = 200 integer*4 :: increment = 20 ! Allocatables integer*4 ncurrent integer*4, allocatable :: scurrent(:) real*8, allocatable :: tcurrent(:) contains !------------------------------------------------------------ subroutine AllocateViewer(ierr) implicit none integer*4, intent(out) :: ierr allocate(scurrent(G_ncurrent+1),stat = ierr) if (ierr /= 0) return allocate(tcurrent(G_ncurrent),stat = ierr) if (ierr /= 0) return scurrent = 0 tcurrent = 0.0d0 return end subroutine AllocateViewer !----------------------------------------------------------------------| subroutine ReAllocateScurrent(ierr) implicit none integer*4, intent(out) :: ierr ! Local allocatables real*8, allocatable :: r8temp(:) integer*4, allocatable :: i4temp(:) integer*4 :: oldsize, newsize ierr = 0 !-------------------------| oldsize = G_ncurrent newsize = oldsize+increment allocate(i4temp(newsize+1), stat=ierr) if (ierr == 0) then i4temp(1:oldsize+1) = scurrent call move_alloc(i4temp, scurrent) endif if (ierr == 0) then allocate(r8temp(newsize), stat=ierr) if (ierr == 0) then r8temp(1:oldsize) = tcurrent call move_alloc(r8temp, tcurrent) endif endif if (ierr == 0) then G_ncurrent = newsize endif end subroutine ReAllocateScurrent [/cpp]
when the program dies the debug shows that oldsize is 200, newsize is 220 and the ierr return status from the allocate is zero. The failure appears to be in the move_alloc because of thereference to RtlFreeHeap(or might possibly be the assignmentof the old values to the new array) as though it were going past the end of the array. But I wonder if it could be a memory fragmentation problem (but then why is allocateierr==0?) though I am not ruling out Heisenbugs.
This occurs with IVF v9.1.028 I will be trying v10.1.025 later.
Has anyone experienced anything similar ?
Les
Link Copied
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Weuse array reallocation a lot in our code, as the data models grow. In this particular instance the model is big (though not as big as some I have seen) andone particular program runs for some 5+ hours before it dies with the following error :
[cpp]HEAP[viewer.exe]: Heap block at 05B24F48 modified at 05B252C4 past requested size of 374
Windows has triggered a breakpoint in viewer.exe.
This may be due to a corruption of the heap, and indicates a bug in viewer.exe or any of the DLLs it has loaded.
The output window may have more diagnostic information
HEAP[viewer.exe]: Invalid address specified to RtlFreeHeap( 03A20000, 05B24F50 )
Windows has triggered a breakpoint in viewer.exe.[/cpp]
Has anyone experienced anything similar ?
Les
In my experience,
[cpp]Heap block at 05B24F48 modified at 05B252C4 past requested size of 374[/cpp]
is a sign of write-out-of-bounds problem somewhere, rather than a memory manager problem (which I, IIRC, haven't encountered in any flavor of Visual Fortran since DVF5.0). The error shows up when debug version of C run-time library (RtlFreeHeap) takes a look at guard block before and/or after the array being deallocated, and finds it overwritten.
So, you have heap corruption somewhere, but (assuming that you do have at least /check:bounds on) I suppose the conditions are such that the bounds checking misses it (writing past assumed size argument?). Good luck in searching for the cause -- you'll need it.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
In my experience,
Heap block at 05B24F48 modified at 05B252C4 past requested size of 374
is a sign of write-out-of-bounds problem somewhere, rather than a memory manager problem (which I, IIRC, haven't encountered in any flavor of Visual Fortran since DVF5.0). The error shows up when debug version of C run-time library (RtlFreeHeap) takes a look at guard block before and/or after the array being deallocated, and finds it overwritten.
So, you have heap corruption somewhere, but (assuming that you do have at least /check:bounds on) I suppose the conditions are such that the bounds checking misses it (writing past assumed size argument?). Good luck in searching for the cause -- you'll need it.
Thanks Jugoslav,I suspected as much, but hoped it was not. We do have check:bounds on and checkuninitialized variables, so I guess I shall just have to dig a little deeper.
Les
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Thanks Jugoslav,I suspected as much, but hoped it was not. We do have check:bounds on and checkuninitialized variables, so I guess I shall just have to dig a little deeper.
374 is hex, evaluating to 884 dec. When divided by 4, it gives 221. That implies that the corruption happened after your 220-long integer(4) array.
Note that "data breakpoints" sort of work in Intel Fortran, i.e. you can watch a single memory address (Debug/New Breakpoint/New data breakpoint/Set language to C; I'm not sure if it works in 9.1). If you're lucky, you can set a breakpoint at 0x05B252C4 and see when it gets modified.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Les,
Prior to hunting down your heap corruption ask youself:
Is your application multi-threaded?
If so, is your reallocation thread safe?
Jim Dempsey
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Les,
Prior to hunting down your heap corruption ask youself:
Is your application multi-threaded?
If so, is your reallocation thread safe?
Jim Dempsey
At the moment it is single threaded. The original code goes way back (started on Apollo hardware before migrating to pc), I and another colleague (no longer here)added the module stuff and mademany of the arrays re-allocatable in the way shown above.
Thinking about what Jugoslav said, I see that the integer array scurrent is always 1 bigger than tcurrent (201 vs 200 initially)so it does help narrow down where to look. I had put conditional break points just after all the calls to allocate (in other modules too not just this one), to catch if ierr was not zero but the debug showed it was zero when the heap error occured.
5 or more hours is a long time to wait for the program to die so I'm taking to running it overnight and hope we don't get a power cut.
Les
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
At the moment it is single threaded. The original code goes way back (started on Apollo hardware before migrating to pc), I and another colleague (no longer here)added the module stuff and mademany of the arrays re-allocatable in the way shown above.
Thinking about what Jugoslav said, I see that the integer array scurrent is always 1 bigger than tcurrent (201 vs 200 initially)so it does help narrow down where to look. I had put conditional break points just after all the calls to allocate (in other modules too not just this one), to catch if ierr was not zero but the debug showed it was zero when the heap error occured.
5 or more hours is a long time to wait for the program to die so I'm taking to running it overnight and hope we don't get a power cut.
Les
A couple hints more:
(0x05B252C4 - 0x05B24F48)/4 = 223.
It appears that you have silent overwrite past the end of array. I can replicate the behavior with the following single program (which doesn't show an out-of-bounds access, but a heap corruption at deallocate). Also note that the "requested size" is 4 bytes bigger than the actual array size, i.e. allocation of 220 elements gives "requested size" of 0x374:
[cpp]program heap integer, allocatable:: foo(:) allocate(foo(220)) foo = 42 call badheap(foo) deallocate(foo) end program heap !--------------------- subroutine badheap(foo) integer foo(*) foo(223) = Z'BAADF00D' end subroutine badheap [/cpp]So, if you can find out which array caused the problem (the one that failed to deallocate), pay attention to places where it's passed to a subroutine as an assumed-size intent(inout). There lie your dragons.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Les,
Extending Jugoslav's information into a diagnostic try the following
Your allocation/deallocation/reallocation routines are isolated therefore easy to change.
First check your code to see if you are using size(array) for either of the two arrays. You coule be obtaining the size of the +1 array and then storing into the +0 array at the size index of the +1 array.
If not using size(array) change the allocation routine to allocate an additional cell for each array and then insert a signature value into the extra cell. Use a value that you would not expect in your dataset and would not by chance also equal the contents of the heap signature bytes (you can compare the prior contents to your signature as a first step, if equal, change signature).
Now place into your code a debug compiled test of the signatures. Good candidates are
1) immediately before the realloc
2) immediately before the delete
3) in the outer layers of your programming onion insert tests before and after subroutine calls
4) work your way deeper into the onion
Make your test a subroutine call such that you have but one place to insert a break point.
For Intel eyes:
Wouldn't it be a nice feature enhancement for developers if you add a diagnostic call
call BreakOnMemoryChange(VariableReferenceHere, code)
Where code can be Enable, Disable, number of bytes, etc...
That is to say a function whereby the programmer can set and reset hardware breakpoints.
Jim Dempsey
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
In order to see if one of my allocatable arrays was being overwritten (as was apparently the issue in this post), I made a subroutine that deallocates every allocated array in the whole program. Whether I execute this at the end of the program or just before the error, it executes fine. I am at wit's end and at a dead end. My only thought is to try to compile under Linux and see if that implementation gives me any more information.
I gather these types of errors are pernicious. I've had similarly bizarre errors in the past and have always worked through them somehow, but this one has me at a standstill. Any suggestions would be greatly appreciated.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
In order to see if one of my allocatable arrays was being overwritten (as was apparently the issue in this post), I made a subroutine that deallocates every allocated array in the whole program. Whether I execute this at the end of the program or just before the error, it executes fine. I am at wit's end and at a dead end. My only thought is to try to compile under Linux and see if that implementation gives me any more information.
I gather these types of errors are pernicious. I've had similarly bizarre errors in the past and have always worked through them somehow, but this one has me at a standstill. Any suggestions would be greatly appreciated.
Again, any information would be appreciated. Right now my workaround is a shorter file name, and that's not a great solution.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
>>When the TRIMmed length of the file name is less than 111, the program runs fine....
>>Right now my workaround is a shorter file name, and that's not a great solution.
As a work around you could use GETDRIVEDIRQQ and CHANGEDIRQQ
If you wish to save the current directory for the drive passed to the HDF sfstart use GETDRIVEDIRQQ to save the current directory on that drive. Then use CHANGEDIRQQ to set the current directory for the drive letter where the file is to reside.
Assume:
D:Realy Long Path Herefoo.hdf
You locate the split between the drive/path and file name and trim off the file name
D:Realy Long Path Here
Then use CHANGEDIRQQ to set the current directorypath for that drive
Next, when you specify the file spec to HDF sfstart, combine the drive letter and the file name (omit the )
D:foo.hdf
If needed, then restore the old "current directory" for the drive.
Note, if path is on network, you can either map a network drive (to the long path) or use a share name to the long path.
Jim Dempsey
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Jim:
Thanks for the changedir ideas. That would be a surefire way to assure the path names were short enough.
We still want to make sure it's not a problem on our end of overwriting memory.
Evan
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
>>We still want to make sure it's not a problem on our end of overwriting memory.
LENTRIM is your friend (before you concatinate two strings)

- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page