Off-by-one-error in array access when using array slice in BIND(C) subroutine

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.

Hi Hakostra! I’ll take a look at this along with your other two issues and get you an engineering report number if I’m able to determine it’s actually a compiler issue (which it, like the other two, appear to be).

Hey Hakostra - I have reported this issue to engineering as TPR#36128. Thank you for bringing it to our attention! As always, please let us know if you run into any other issues. I’ll let you know about a fix when engineering gets to the issue.

Cheers,

Seth.

Hi! Engineering has fixed this in our latest release, 25.3. If you run into anymore issues, please let us know!

Great, thanks for letting me know. I will install this release and try!

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.