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

Problems with Allocatable arrays (real8). Accessing ranges not allocated in arrays in Fortran.

Julio
Novice
1,659 Views

Dear Community,

I am getting a very weird result when I try to access a non existent range in a allocated array.

I define my array as:

 

 

integer, parameter :: dp = 8
real(kind=dp), dimension, allocatable(:,:) :: u_out, u_old
Integer :: Imax = 5, Jmax = 11
allocate (u_out(Imax-1,Jmax),u_old(Imax,Jmax))

 

 

Notice that the array "x" has a 1 extra row compared to the "x_out". The idea is to copy the contiguous element from the array "x" to "x_out". The last row in the array "x" represents the ghost cells (MPI).

After some computations, I copy the contiguous elements in the following manner:

 

 u_out(:,:) = u_old(1:imax-1,:)

 

However, when I am writing the values from each array to a file, to double check that the ghost cells are skipped in the array "u_out" I am surprised that the "segmentation fault" error does not come up. Look the following do loop:

 

  do j = 1, jmax
     do i = 1 , imax
       write(131,*) u_old (i,j), "|",  u_out(i,j)
     enddo
  enddo

 

Remember that Imax = 5 and Jmax=11. More importantly, the allocated arrays size are different. Neverthless, the writes proceeds with no problem .. Why is this ? How can I access a value that does exists in "u_out". e.g: u_old(5,11).

I also tried to write values such as:

u_out(10,1) and it returns a value.... How is this possible if that size is larger than the one I did allocate?

It is important to mention that the "allocate" takes place in one subroutine and the copy and write to the file takes place in another subroutine. Does the "out of scope" a apply here ?

 

 

Thanks

Julio

 

 

 

 

Labels (1)
0 Kudos
7 Replies
jimdempseyatthecove
Honored Contributor III
1,641 Views

Fortran permits indexing beyond array bounds (may pagefault when address not available)

You can enable Runtime Checks for array bounds exceeded (at the expense of slower run times).

Jim Dempsey

0 Kudos
Steve_Lionel
Honored Contributor III
1,633 Views

"Fortran permits indexing beyond array bounds (may pagefault when address not available)"

No, Fortran, the language, doesn't permit this. If you do it, the results are unpredictable.

jimdempseyatthecove
Honored Contributor III
1,608 Views

"Fortran permits indexing beyond array bounds (may pagefault when address not available)"

No, Fortran, the language, doesn't permit this. If you do it, the results are unpredictable.

Bad choice of words on my part, while Fortran does not authorize access beyond array bounds, it is rather permissive, it that it will not inhibit this type of behavior (excepting when runtime checks are enabled, and/or at compile time when the compiler can determine bounds error).

Jim Dempsey

Julio
Novice
1,576 Views

Thank you very much for your input. I do appreciate the time you all have spent providing me with your point of view. 

Today, I spent more than half an hour because one of the allocatable arrays was indexed with a larger value. The loop was nested with a bunch of counters that was difficult to spot. So, working with dynamic arrays is dangerous, unless I can put some checks. Could you please provide me with the flags that I should use to avoid this issue? 

As Dr.Fortran pointed out, the outcome is quite unpredictable. 

@John_Campbell I'll try your suggestion, I think that the outcome is as you mentioned, the address will be the same. Although this does not solve the problem, indeed it makes it harder to spot. 

 

@andrew_4619 Sorry, but my knowledge in computer science is very limited and I do not understand the term "explicit interfaces". This case has all variables declared in a simple program, I am not using modules nor subroutine in this "proof of concept" program. This will be implemented in a larger program where all variables are sitting in a module and each subroutine sees the module. 

 

Julio

0 Kudos
andrew_4619
Honored Contributor II
1,574 Views

andrew_4619_0-1594388623021.png

That is a good check for mismatched parameters on calls.......

andrew_4619_1-1594388741732.png

Those two will throw runtime errors on array size problems and are useful for debug builds to find error. For release build these checks can have a speed penalty.

andrew_4619
Honored Contributor II
1,637 Views

It depends how you declare  the subroutines variables, if they are deferred shape and you have  explicit interfaces (e.g . the subroutines are in modules) then the compiler will know the array bounds by default and would throw an error.  Make a simple complete code that shows the 'error' and post it and you will get some specific advice.

0 Kudos
John_Campbell
New Contributor II
1,623 Views

Why don't you try the following and review the address of each element of u_old and u_out

  write (131,*) 'Address of array elements'
  do j = 1, jmax
     do i = 1 , imax
       write(131,*) i,j," |u_old",loc(u_old (i,j)), " |u_out",  loc(u_out(i,j))
     enddo
  enddo

Hopefully you will find u_out(5,1) and u_out(1,2) have the same location.

Only u_out(5,11) is outside the allocated range of array u_out .

Reply