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

Access violation in DEALLOCATE

murpup1
Beginner
1,736 Views
Hi All,

I have an application that throws an access violation when it hits a DEALLOCATE statement. The code below illustrates what I believe to be a boiled down version of what my code does, without all complexity:

MODULE one

TYPE test
INTEGER, POINTER, DIMENSION(:) :: subArray,
END TYPE test

TYPE(test) :: var

END MODULE one

MODULE two

USE one

CONTAINS

SUBROUTINE DoSomething
TYPE(test) :: opt
! Allocate the memory
CALL AllocMem(opt)

! Code that uses the subArray substructure
opt%subArray = 1
someVal = opt%subArray(3)

! Free the allocated memory
CALL FreeMem(opt)
END SUBROUTINE DoSomething

SUBROUTINE AllocMem(block)
TYPE(test) :: block
ALLOCATE(block(50))
END SUBROUTINE AllocMem

SUBROUTINE FreeMem(block)
TYPE(test) :: block
DEALLOCATE(block%subArray) ! Code dies here
END SUBROUTINE FreeMem

END MODULE two


Essentially, I call one routine to allocate a pointer array in a derived type, use that array, then call another routine to deallocate the memory. There is lots of other code and and operations on other data mixed in, and the derived type has more than just 1 substructure, but you get the idea.

If I run my code in the debugger, it dies right at the DEALLOCATE statement with the following stack trace:

V31113_R5TRIPMAP! __sbh_free_block + 371 bytes
V31113_R5TRIPMAP! free + 40 bytes
V31113_R5TRIPMAP! for_deallocate + 101 bytes
V31113_R5TRIPMAP! for_dealloc_allocatable + 85 bytes
CVTR5GLOBALDATA::CONVERTR5OPTIONS() line 186 + 67 bytes

Looking in the debugger, right before the DEALLOCATE is called, the array is properly allocated in that all array elements are there, and no data appears corrupted.

If I move the DEALLOCATE statement up out of FreeMem and right after the call to AllocMem, ala

CALL AllocMem(opt)
DEALLOCATE(opt%subArray)

the code still dies.

If I put the DEALLOCATE statement in AllocMem, then it deallocates the memory as expected.

I figure that somewhere else in the code, the code is clobbering memory that is adjacent to the array that I am attempting to deallocate, but before I spend a buttload of time tracking this down, my question is this:

Is it conceivable that this is instead a compiler bug?

Chris
0 Kudos
8 Replies
Jugoslav_Dujic
Valued Contributor II
1,736 Views
Well, it is conceivable but very unlikely. What you observe look like typical symptoms of array bounds violations (expecially referring to subArray(0)); switch on "Array bounds checking" in Project/Settings/Fortran/Run time and fix the code when you find out where it occurs.

Jugoslav
0 Kudos
nijhuis
Beginner
1,736 Views
Though the presented code does not compile at all in CVF6.6B, I think it shows a big mistake.
The subroutine AllocMem tries to allocate 50 elements of the derived type test, thus 50 elements containing a pointer to subarray; subarray itself is never allocated (at least in the presented code). But in the subroutine FreeMem you deallocate subarray, which is never allocated.

Guus
0 Kudos
murpup1
Beginner
1,736 Views
Yeah, array bounds checking (and every other run-time check for that matter) is already turned on. What I get is specifically an access violation. The array is dimensioned from 1 to 90 (in my actual code; the example shows 50).

What I figured MIGHT be happening is that some sloppy coding on our part (leading to clobbered memory somewhere) is uncovering a flaw in the DEALLOCATE logic internal to the compiler. But I have been coding long enough to know that the mistakes are almost always my fault, so that is my first assumption. My only reason for asking the question is that this is going to be an incredibly difficult bug to track down and I wanted to make sure I wasn't chasing a ghost. Nobody else on my development team can reproduce this problem, so the weight is solely on my shoulders.

Thanks,
Chris
0 Kudos
murpup1
Beginner
1,736 Views
Regarding your response, Guus

That is just a flaw in my example. I should have written

ALLOCATE(block%subArray(50))

So my actual code is alright in that respect.

Sorry for the flaw,
Chris
0 Kudos
Jugoslav_Dujic
Valued Contributor II
1,736 Views
Before you continue, and since it's reproducible only in one machine, I'd first ask the classic sanity check:

Are you sure you're debugging the same code you see on the screen? Screwed date/time on your machine or source files or .obj files can cause havoc.

Ok, if you have passed the first test, I'd try to tackle it in the following manner:

- Immediately after allocate, open "Memory" debugger window and type the name of your derived-type variable. It should contain only the array descriptor, i.e. its contents shouldn't be changed during its lifetime.

- Step through the code in large steps and see whether the contents change; if they do, repeat it in smaller steps until you find the offending line. If they don't, um, I'm running out of ideas.

- If you put an stat= into deallocate, what does it return?

Jugoslav
0 Kudos
murpup1
Beginner
1,736 Views
I am not really sure what you mean by open the Memory window and type in the name of the derived type variable. Perhaps you meant the Watch window???

If I click on View, Debug Window, Memory, it opens up a dialog box whose top entry box indicates it is expecting a memory address, not variable name. The lower part of the box is filled with question marks for each memory address.

This brings up a question. Is it possible to watch locations in memory adjacent to a variable of interest? Is there some way to use the memory formatting symbols (i.e. ma, m, mb, etc) to print out the memory location of a variable, then use that info to track it in the Memory window?

Thanks for your time and patience on this, Jugoslav. I lurk on this site every so often. If it weren't for guys like you donating your time for the greater good, the FORTRAN community would be much worse off.

Chris
0 Kudos
murpup1
Beginner
1,736 Views
BTW, there is stat argument passed, but since the DEALLOCATE never returns, it doesn't tell me anything useful. I tried removing it, but that made no difference.
0 Kudos
Jugoslav_Dujic
Valued Contributor II
1,736 Views
If I recall correctly, typing variable name in the Memory window is sufficient. In any case, typing LOC(Variable) in either the memory window or watch window surely works. Further, "LOC(Variable),x" in the watch window gives the address in hexadecimal. Each structure member which is a POINTER occupies 4 bytes + 24 bytes per each array dimension; note that this is only a descriptor -- it contains no data. Real data are located at the address pointed to by the first 4 bytes. It's too bad that it isn't possible to open multiple Memory windows simultaneously.

Thanks for your compliments.

Jugoslav
0 Kudos
Reply