Intel® Fortran Compiler
Build applications that can scale for the future with optimized code designed for Intel® Xeon® and compatible processors.
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.

Error using dynamic memory

blischke
Beginner
592 Views

I'm getting the error:

forrtl: severe (157): Program Exception - access violation

when I'm trying to use allocatable arrays passed as arguments. I've distilled the code down
to what's below. The error seems to be when it's using Z when calling NEXT; it never
starts executing NEXT.

If I uncomment the lines with C1, it gets the same error with the ALLOCATED(Z) command.
If I use pointers instead, uncommenting the C2 lines, it gets the same error on the ASSOCIATED(Z)
command. For all cases, the output is just "Calling NEXT."

I suspect I'm just not passing the complex allocatable array correctly, but I don't see
any other way to try that makes sense.

main.f90:
program main
USE Zmatrix, ONLY : Z
INTEGER NZMAX
PARAMETER (NZMAX=20000000)

ALLOCATE(Z(NZMAX))

CALL driver(Z)

STOP
END

zmatrix.f90:
MODULE Zmatrix
COMPLEX, ALLOCATABLE, TARGET :: Z(:)
END MODULE Zmatrix

driver.f90
SUBROUTINE DRIVER(Z)

COMPLEX, ALLOCATABLE, TARGET :: Z(:)
C2 COMPLEX, POINTER :: Z(:)
REAL RVAR

CALL INTERMEDIATE(Z, RVAR)

RETURN
END

intermediate.for
SUBROUTINE INTERMEDIATE(Z, RVAR)

COMPLEX, ALLOCATABLE, TARGET :: Z(:)
C2 COMPLEX, POINTER :: Z(:)
REAL RVAR

WRITE(*,*) 'Calling NEXT.'
C1 WRITE(*,*) 'ALLOCATED(Z) = ', ALLOCATED(Z)
C1 WRITE(*,*) 'Called ALLOCATED'
C2 WRITE(*,*) 'ASSOCIATED(Z) = ', ASSOCIATED(Z)
C2 WRITE(*,*) 'Called ASSOCIATED'

CALL NEXT(Z, RVAR)

RETURN
END

next.for:
SUBROUTINE NEXT(Z, R)

COMPLEX, ALLOCATABLE, TARGET :: Z(:)
REAL R

WRITE(*,*) 'Entered FUNC.'

CALL ONE(Z,R)
CALL TWO(Z,R)
CALL THREE(Z,R)
CALL MANY(Z,R)

RETURN
END

one.for:
SUBROUTINE ONE(Z,R)

COMPLEX Z(*)
WRITE(*,*) 'ONE'
RETURN
END

two.for, three.for, and many.for similar to one.for

output:
Calling NEXT.

error message(memory locations may vary):
forrtl: severe (157): Program Exception - access violation
Image PC Routine Line Source
testcode.exe 004011A7 Unknown Unknown Unknown
testcode.exe 004010D0 Unknown Unknown Unknown
testcode.exe 00401542 Unknown Unknown Unknown
testcode.exe 004404F9 Unknown Unknown Unknown
testcode.exe 004312F5 Unknown Unknown Unknown
kernel32.dll 77E8141A Unknown Unknown Unknown
0 Kudos
4 Replies
Steven_L_Intel1
Employee
592 Views
Doctor Fortran has explicit advice for you...
0 Kudos
blischke
Beginner
592 Views

Thanks. I was able to get the sample code to compile, although I'm not sure if I'm out of the
woods yet.

For those of you playing along at home, I modified main.f90 to add

INTERFACE
SUBROUTINE DRIVER (Z)
COMPLEX, ALLOCATABLE, TARGET :: Z(:)
END SUBROUTINE DRIVER
END INTERFACE

after the USE statement, and added

INTERFACE
SUBROUTINE INTERMEDIATE (Z, R)
COMPLEX, ALLOCATABLE, TARGET :: Z(:)
REAL ::R
END SUBROUTINE INTERMEDIATE
END INTERFACE

after the SUBROUTINE line in driver.f90.

How come I didn't have to add an interface block to intermediate.f90 for the call to NEXT?

Here's the overarching problem: I have a large legacy code written in F77. Originally, Z was
statically declared COMPLEX Z(NZMAX) in the main program, which was originally driver.for. I
made Z allocatable because I'm compiling this for an EM64T with 8 GBytes of RAM, and I was told
(by you, thanks again) that I needed to use dynamic allocation to have an array over 2 (IIRC)
GBytes. For clarity, I pulled the allocation into main.for, and had it call driver.for (now
driver.f90) with the large array passed in.

But... I've got all these routines ONE, TWO, ..., MANY that work with Z. And they call lots of
other routines. Will I need to change all the
COMPLEX Z(*)
statements to
COMPLEX, ALLOCATABLE, TARGET :: Z(:)
statements? That's not horribly bad, but if I can avoid it, I'd like to. In C, we can more-or-less
freely interchange arrays and pointers when passing arguments into functions.

I can pass in a complex pointer to a routine accepting complex Z(*), and it works on my regular
Windows XP system. Will this still work on the EM64T system, with NZMAX such that Z is, say, 7
GBytes?

If I need to change all the COMPLEX Z(*) statements, will I also need INTERFACE blocks for every
routine as well?
0 Kudos
blischke
Beginner
592 Views

Apparently I do need the INTERFACE block for NEXT in INTERMEDIATE. Without it,
ALLOCATED(Z) returns .TRUE. immediately before the call to NEXT, but returns
.FALSE. at the start of NEXT. With it, ALLOCATED(Z) returns .TRUE. within NEXT.

With a little more testing, I find that if I give Z some values in main.for, I
can write those values to the screen in ONE if Z is declared
COMPLEX Z(*)
but I get error 157 if I try to write their values if Z is declared
COMPLEX Z(:)
Unfortunately, I'm guessing Z(*) won't work on the EM64T system with a large
NZMAX. I had my code working on my system, and compiling for the EM64T system,
a while back. When we tried running it, it crashed complaining that Z was
declared with a negative size.

There's no way I'm going to be able to avoid making an INTERFACE block for EVERY
routine that handles Z, is there? If so, I've got at least 34 routines that need
INTERFACE blocks, and need to be modified. Is there any way that I can be sure
I've found them all?
0 Kudos
Steven_L_Intel1
Employee
592 Views
The problem is that you made more work for yourself than necessary. Changing the argument declarations to

Z(*)




is the correct solution - then you would need to make any other changes, including the explicit interface. By making these arguments assumed-shape, you added the requirement for the explicit interface.

Message Edited by Steve_Lionel on 12-09-2005 05:14 PM

0 Kudos
Reply