Intel® Fortran Compiler
Build applications that can scale for the future with optimized code designed for Intel® Xeon® and compatible processors.

heap corruption error

carlos8410
Beginner
2,471 Views
Hi,

I created some ALLOCATABLE variables, I defined the size for them, and after using them, I DEALLOCATE them. Then the heap corruption error pop-out. The error message is listed below in sequence. And the source code is also listed.

This is strange that the code doesn't have this problem before, but after I fixed an error (one of the variable is not assigned value.) in the code, this error come out. And the heap corruption does not happen when I use the pointers, but happens when I release them.

This is the first warning window appears:
==========================================
Windows has triggered a breakpoint in powell_test.8.26.exe.

This may be due to a corruption of the heap, which indicates a bug in powell_test.8.26.exe or any of the DLLs it has loaded.

This may also be due to the user pressing F12 while powell_test.8.26.exe has focus.

The output window may have more diagnostic information.
==========================================


This is the error message I got from the debug.
============================================
Debug Error!

Program:....

HEAP CORRUPTION DETECTED: after Normal block (#103) at 0x003A3748.
CRT detected that the application wrote to memory after end of heap buffer.
-------------------------------------------------------------------------------
* If this ASSERT fails, a bad pointer has been passed in. It may be
* totally bogus, or it may have been allocated from another heap.
* The pointer MUST come from the 'local' heap.
*/
_ASSERTE(_CrtIsValidHeapPointer(pUserData));
==================================================


Below is the source code. I just copy the related code, the whole file is too large.
==================================================
...
ALLOCATABLE :: X(:), XBASE(:), XOPT(:), XNEW(:), GQ(:), D(:),
1 FVAL(:), PQ(:), HQ(:), VLAG(:), W(:), XPT(:,:), BMAT(:,:),
2 ZMAT(:,:)
...
ALLOCATE (X(1:N), XBASE(1:N), XOPT(1:N), XNEW(1:N), GQ(1:N),
1 D(1:N), FVAL(1:NPT), PQ(1:NPT), HQ(1:NH), VLAG(1:NDIM),
2 W(1:10*NDIM), XPT(NPT,N), BMAT(NDIM,N),
3 ZMAT(NPT,NPTM))
...
...
...
OPEN ( 15, file='D:System FileDesktopFortraninput2.inp' )

WRITE (15, 10) N,NPT,IPRINT,NPTM,NF,NP,NDIM,NH,IDZ,KOPT,KNEW,
1 RHO_FLAG,JUMP_FLAG,FLAG_310
WRITE (15, 11) RHOEND,DELTA,DIFFA,DIFFB,XOPTSQ,F,FOPT,
1 RHO,DNORM,TEMP,BETA
WRITE (15,12) (X(I),I=1,N)
WRITE (15,13) (XBASE(I),I=1,N)
WRITE (15,14) (XOPT(I),I=1,N)
WRITE (15,15) (XNEW(I),I=1,N)
WRITE (15,16) (GQ(I),I=1,N)
WRITE (15,17) (D(I),I=1,N)
WRITE (15,18) (FVAL(I),I=1,NPT)
WRITE (15,19) (PQ(I),I=1,NPT)
& nbsp; WRITE (15,20) (HQ(I),I=1,NH)
WRITE (15,21) (VLAG(I),I=1,NDIM)
WRITE (15,22) (W(I),I=1,10*NDIM)
DO I=1,NPT
WRITE (15,23) (XPT(I,J),J=1,N)
END DO
DO I=1,NDIM
WRITE (15,24) (BMAT(I,J),J=1,N)
END DO
DO I=1,NPT
WRITE (15,25) (ZMAT(I,J),J=1,NPTM)
END DO

CLOSE (15)

DEALLOCATE(X, XBASE, XOPT, XNEW, GQ, D, FVAL, PQ, HQ, VLAG, W,
1 XPT, BMAT, ZMAT)

END







0 Kudos
6 Replies
Jugoslav_Dujic
Valued Contributor II
2,472 Views
HEAP CORRUPTION DETECTED: after Normal block (#103) at 0x003A3748.
CRT detected that the application wrote to memory after end of heap buffer.


This indicates that you had a silent out-of-array-bounds write somewhere between allocation and deallocation. If you haven't, please compile with array bounds checking in debug configuration. However, even with that switch, IVF (as far as I know) can not catch out-of-bounds access for assumed-size argument arrays.

Hints to debug the problem:
1) Divide the final DEALLOCATE into one-array-by-one statements; that will point you to the likely (not necessarily!) array which is the culprit
2) While debugging, switch on "Memory" window and type 0x003A3748. That location is in a "guard block" filled by ALLOCATE, and shouldn't be written into. Execute the code repeatedly in steps (Ctrl+F10) by "divide and conquer" until you find which exact statement overwrote that location -- that is where you have the heap corruption.

(A "data breakpoint" would catch the overwriting 2) automatically, but it cannot be reliably set to work with Fortran code. Try it though, you might get lucky.)


0 Kudos
carlos8410
Beginner
2,472 Views
I do splite the deallocate statement into separate statements and find where the problem is.
But to save time, I use another way to solve this problem. As I deallocate the arrays at the end of the code, so I just delete the deallocate statement. Because after the whole loop, these allocatable arrays will be released automatically. And this does work. But I still have concern on whether this will cause further problem or the error will come when some condition is satisfied.
0 Kudos
Steven_L_Intel1
Employee
2,472 Views
Which compiler version are you using? I know we have fixed bugs similar to this in the past. If you can come up with a small but complete test case that shows the problem, we'd like to see it.
0 Kudos
jimdempseyatthecove
Honored Contributor III
2,472 Views

Carlos,

Removal of the deallocate statement does not fix the problem, it fixes the symptom. Your symptom indicates an underlaying problem where the array descriptor is being modified or where some memory write access wrote beyond the end of an array and overwrote the hiddenallocation header data that preceeds the pointer returned from allocation.

Something allocated to memory that resides before the memory of the array in error andhad been written to beyond the end of the array. Example:

allocate(A(N))
allocate(B(N))
A(N+something) = value

The symptom of the problem (error on deallocate of B) will depending on what incorrect element ofA was written. You might observe the error when writing A(N+1) or A(N+2) but not observe the problem when writing A(N+3).

Removal of the deallocate does not correct the error in the code that is (may) cause B to be overwritten.

Note, it is possible that the incorrect element of A only overwrites the hidden allocation header and thus B(1), B(2) ... never get corrupted. In this case the error in the program does not cause a crash but it does not fix the program.

Turn on the runtime diagnostic to check for access beyond array bounds and see if the error is caught or see if the error continues to appear at deallocation. If it continues at deallocation then you may be calling a library or C/C++ function that is writing beyond end of the array.

Additional things to try is to insert diagnostic code (use conditional compilation directives so you can turn it on and off)

! The following is your arrays in a module
! add target attribute
real, allocatable, target :: A(:)
real, allocatable, target :: B(:)
! create debugging module that has
real, pointer :: Aguard
real :: AguardValue
real, pointer :: Bguard
real :: BguardValue
 contains
subroutine BugCheck()
if(Aguard .ne. AguardValue) call FoundBug()
if(Aguard .ne. AguardValue) call FoundBug()
end subroutine BugCheck
 subroutine InitializeBugCheck()
Aguard => A(N+1)
AguardValue = Aguard
Bguard => B(N+1)
BguardValue = Bguard
end subroutine InitializeBugCheck
your program add USE for BugCheck and calls to initialize
and test for bugs (use conditional compilation directives)

allocate(A(N))
allocate(B(N))
call InitializeBugCheck
...
! insert this in places in your code
call BugCheck()
...
deallocate(B)
deallocate(A)
Jim Dempsey

0 Kudos
carlos8410
Beginner
2,472 Views
Thank you for your help.

For the compiler, it's Intel Fortran Compiler 10.1.021. And I install the VS2008 and make the compiler integrated into it. The whole code is very long, actually, I am doing some modification to it and make it access to other application. So I don't have a way to paste all of it here. But let me try Jim's method first to see if I can fix the problem.
Thanks Jim for the detailed suggestion!
0 Kudos
jimdempseyatthecove
Honored Contributor III
2,472 Views

Carlos,

One thing for me to point out.

The old values (AguardValue, ...) may contain unnormalized floating point numbers. It is not an error to see NaN or other bad floating point numbers in the saved variables.

If you are using SSE3 instructions you likely will not get an error if the old value is NaN. F87 FPU might error out.

An alternate method is to obtain the address of the first element outside the range and cast it to an integer or integer(8)

type abcd
sequence
union
map
real, pointer :: r
end map
map
integer(8), pointer :: i
end map
integer(8) :: oldValue
end union
end type abcd

type(abcd) :: Aguard
type(abcd) :: Bguard

Aguard.r => A(N+1)
Aguard.oldValue = Aguard.i

Jim Dempsey

0 Kudos
Reply