Once again something I believe is a compiler bug from me… Take the following example:
PROGRAM main
IMPLICIT NONE
INTEGER :: my_array(10)
my_array = 0
WRITE(*, *) "CALL check_array(my_array(2:5))"
CALL check_array(my_array(2:5))
WRITE(*, *) "my_array: ", my_array
WRITE(*, *) ""
WRITE(*, *) "CALL check_array(my_array(8:9))"
CALL check_array(my_array(8:9))
WRITE(*, *) "my_array: ", my_array
WRITE(*, *) ""
WRITE(*, *) "CALL check_array(my_array(:))"
CALL check_array(my_array(:))
WRITE(*, *) "my_array: ", my_array
WRITE(*, *) ""
WRITE(*, *) "CALL check_array(my_array)"
CALL check_array(my_array)
WRITE(*, *) "my_array: ", my_array
CONTAINS
SUBROUTINE check_array(res) BIND(C)
INTEGER, INTENT(out) :: res(:)
INTEGER :: i
WRITE(*, *) "SIZE(res): ", SIZE(res)
DO i = 1, SIZE(res)
res(i) = i
END DO
END SUBROUTINE check_array
END PROGRAM main
With gfortran
, ifx
, ifort
and nagfor
I get results I expect:
CALL check_array(my_array(2:5))
SIZE(res): 4
my_array: 0 1 2 3 4 0 0 0 0 0
CALL check_array(my_array(8:9))
SIZE(res): 2
my_array: 0 1 2 3 4 0 0 1 2 0
CALL check_array(my_array(:))
SIZE(res): 10
my_array: 1 2 3 4 5 6 7 8 9 10
CALL check_array(my_array)
SIZE(res): 10
my_array: 1 2 3 4 5 6 7 8 9 10
With nvfortran
version 24.7 I get:
CALL check_array(my_array(2:5))
SIZE(res): 4
my_array: 0 0 1 2 3
4 0 0 0 0
CALL check_array(my_array(8:9))
SIZE(res): 2
my_array: 0 0 1 2 3
4 0 0 1 2
CALL check_array(my_array(:))
SIZE(res): 10
my_array: 0 1 2 3 4
5 6 7 8 9
CALL check_array(my_array)
SIZE(res): 10
my_array: 1 2 3 4 5
6 7 8 9 10
I.e. the result after the three first calls to check_array
, when array slices are used, is wrong. check_array
“see” the right array size, but the results are stored in a off-by-one position (i.e. shifted one location to the right)!! I cannot rule out a possibility for an invalid memory access in this example (where is the last number 10 stored in the third example, in a memory location outside the array??? This could trigger a segfault).
Also, when the INTENT(out)
is changed to INTENT(inout)
in check_array
it seems to work. However, check_array completely define the entire output independent on any initial values in the array, so I believe INTENT(out)
is correct wrt. the Fortran language and allowed here (it is a great workaround and temporary solution, though!!).
Please note the BIND(C)
on the subroutine check_array
. When this is taken away everything also works. However, my application is the usage of the CFI_cdesc_t
array descriptors and BIND(C)
routines/interfaces, therefore this is important.