L.J
L.J

Reputation: 1084

Index of array out of range

I am confused how Fortran handle the situation if the index for referencing an element of an array is actually out of its supposed range.

Here is a simple code to illustrate the problem:

PROGRAM test_matrix_out

USE mod_writearray

IMPLICIT NONE
INTEGER :: i,j,m,n
REAL    :: k
REAL, Dimension(:,:),ALLOCATABLE :: A

m = 3
n = 4
ALLOCATE(A(m,n))

k = 1

DO i=1,m
    DO j=1,n
        A(i,j)=k
        k=k+1
    ENDDO
ENDDO

CALL writearray(A)
WRITE(*,*)
WRITE(*,*) A(1,:)
WRITE(*,*)
WRITE(*,*) A(2,:)
WRITE(*,*)
WRITE(*,*) A(0,:)
WRITE(*,*)
WRITE(*,*) A(4,:)
WRITE(*,*)
WRITE(*,*) A(5,:)
WRITE(*,*)
WRITE(*,*) A(100,:)
WRITE(*,*)
WRITE(*,*) A(:,1)
WRITE(*,*)
WRITE(*,*) A(:,2)
WRITE(*,*)
WRITE(*,*) A(:,0)
WRITE(*,*)
WRITE(*,*) A(:,4)
WRITE(*,*)
WRITE(*,*) A(:,5)
WRITE(*,*)
WRITE(*,*) A(:,100)


DEALLOCATE(A)

END PROGRAM test_matrix_out

It gives me the following result:

   1.000000       2.000000       3.000000       4.000000

   5.000000       6.000000       7.000000       8.000000

  0.0000000E+00   9.000000       10.00000       11.00000

   2.000000       3.000000       4.000000      0.0000000E+00

   6.000000       7.000000       8.000000      0.0000000E+00

  0.0000000E+00  0.0000000E+00  0.0000000E+00  0.0000000E+00

   1.000000       5.000000       9.000000

   2.000000       6.000000       10.00000

 -1.0097448E-28  8.9776148E-39  0.0000000E+00

   4.000000       8.000000       12.00000

  0.0000000E+00  0.0000000E+00  0.0000000E+00

 -3.3631163E-44  1.4293244E-43  0.0000000E+00

Why does this happen?

Upvotes: 4

Views: 3461

Answers (2)

M. S. B.
M. S. B.

Reputation: 29381

When you write A(i,j) the compiler calculates the address of of that memory location. See, for example, http://en.wikipedia.org/wiki/Array_data_structure#Multidimensional_arrays. The compiler normally doesn't determine whether this is a legal address according to the rules of the language. Using indices past the dimensions is illegal. It is the responsibility of the programmer not to do this. One of the advantages of Fortran is the ability to add run-time checks for this mistake. The conventional lore is that run-time subscript checking is expensive but I when I have tested I have frequently found the runtime cost to be negligible and sometimes leave it on in production versions of programs.

If you are reading memory the likely consequence of an index mistake will be to obtain a wrong value, unless the memory location is so far off that it is outside the memory belonging to the program, which will create a fault. If you are writing to memory you will corrupt memory elsewhere in the array, belonging to some other variable, or belonging to an internal data structure of the program. See what kind of problems can lack of deallocation cause? for an example question where an index error caused runtime problems with a program.

Upvotes: 7

milancurcic
milancurcic

Reputation: 6241

What you are seeing is that the compiler you use to compile the program is not checking whether the arrays get out of bounds at run-time. So, depending on the compiler and machine, anything goes. At times, array elements that are not explicitly allocated in memory are possible to be referenced, which is what happens in your example. In this case, the value of the element that is out of bounds is whatever value is sitting at that memory address at program run-time. If the memory address requested does not exist or cannot be accessed, the program will fail with a segmentation fault.

I was just looking at the draft of the current Fortran standard, and I could not find any statement about whether accessing array elements out of bounds is a defined behaviour. In order to avoid these issues, compile your program with -C (check bounds) flag. If possible, the program will let you know which element of which array went out of bounds. Use -C during development, but not in production, because it slows down the code tremendously.

Also, for future reference, when asking questions of this kind (e.g. why my program outputs this?), it is best to include information about the compiler being used (with version number) and target architecture.

Upvotes: 5

Related Questions