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 ?
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).
"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).
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.
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.
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 .