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

Allocatable array assignment is prone to access violation

vvnurmi
Beginner
1,124 Views
PROGRAM ARRAY_ASSIGNMENT IMPLICIT NONE INTEGER, DIMENSION( : ), ALLOCATABLE :: ARR1, ARR2 ALLOCATE( ARR1( 10000000 ), ARR2( 2 ) ) ARR1 = 1 ARR2 = 2 ARR1 = ARR2 END PROGRAM ARRAY_ASSIGNMENT

This program contains a programming error. The Intel Fortran Reference Guide says "Array assignment is permitted when the array expression on the right has the same shape as the array variable on the left, or the expression on the right is a scalar."

What I'm worried about is that the compiler doesn't warn me about my error:

c:\\fortran\\arrayassignmenttest>ifort /warn:all arrayassign.f90 Intel Visual Fortran Compiler XE for applications running on IA-32, Version 12.0.1.040 Beta Build 20100608 Copyright (C) 1985-2010 Intel Corporation. All rights reserved. Microsoft Incremental Linker Version 10.00.30319.01 Copyright (C) Microsoft Corporation. All rights reserved. -out:arrayassign.exe -subsystem:console arrayassign.obj c:\\fortran\\arrayassignmenttest>arrayassign.exe forrtl: severe (157): Program Exception - access violation Image PC Routine Line Source arrayassign.exe 00BB1168 Unknown Unknown Unknown arrayassign.exe 00BDD903 Unknown Unknown Unknown arrayassign.exe 00BC93F4 Unknown Unknown Unknown kernel32.dll 771CE4A5 Unknown Unknown Unknown ntdll.dll 7766CFED Unknown Unknown Unknown ntdll.dll 7766D1FF Unknown Unknown Unknown

What seems to happen is that my program reads10000000 INTEGERs from ARR2, reading past the process's allocated memory area, leading to access violation.

If the arrays are not ALLOCATABLE, the compiler realizes the error and tells me about it. With ALLOCATABLE arrays, the error cannot in general be detected at compile-time, but I'm sure there are better alternatives than to trust the programmer and silently compile away.

A) The compiler could warn about a potentially dangerous array assignment, requesting the programmer to specify an explicit array range where to assign, like this:

ARR1( 1 : 2 ) = ARR2

B) The compiler could place run-time asserts against reading past the array on the right hand side of the assignment. The asserts could be removed with strong enough optimization flags to the compiler. Note that the programming error above leads to access violation only occasionally, so the error may be difficult to spot. However, the assignment never makes sense, so a hard exception is better than silent illegal behaviour.

0 Kudos
3 Replies
IanH
Honored Contributor II
1,124 Views
Note that it's actually not a programming error under F2003, but you need to add the /assume:realloc_lhs command line option to ifort to make it do F2003's allocate-on-assignment.

/check:all enables a lot of "run time asserts", but unfortunately not one that catches this sort of error.
0 Kudos
abhimodak
New Contributor I
1,124 Views
Hi IanH

I(:) = J(:) will catch it at run time when /check:bounds is active.

As Steve Lionel has pointed out sometime back writing such partition expressions instead of the whole array syntax (i.e. I = J) makes compiler do (insert) some more checks and hence is slower. May be I am thinking it wrong way, but it looks like a no-win situation. That is, if compiler is to detect something the performance is sacrificed otherwise there is potential of access violation.

May be some other switch can introduced (or the current can be extended) to do the bounds checking in debug mode for whole arrays. As you mentioned that will have to be overwritten when /assume:realloc_lhs is present.

It is time to look if something like this exists in my programs...

Abhi
p.s. I am probably using the term "compiler" quite loosely.
0 Kudos
jimdempseyatthecove
Honored Contributor III
1,124 Views

In the case of

Array = Scalar

Where Array is allocatable and unknown at compile time, the compiler now generates code to find the size of the allocation of Array (or unallocated status).

In the case of

Array = Brray

And /assume:realloc_lhs, and if Array is too small, Array will be reallocated.

In the case of

Array = Brray

And .NOT. /assume:realloc_lhs and if Array and Barray are allocatble and sizes not known

The compiler currently picks the size from one of the arrays (likely Array since it does this in the scalar assignment).
It would be reasonable to request for an option to assert the sizes are equal (when .NOT. /assume:realloc_lhs).

Jim Dempsey
0 Kudos
Reply