Jean-Yves LExcellent
2018-11-20 13:43:39 UTC
Dear gfortran developers,
I hope it is reasonable to report a gfortran problem at this address.
I have a tiny example showing a strange behaviour when accessing the
elements of a pointer array, which is part of a derived type. The
example consists of 3 files (main.F, sub.F, dmumps_root.h, shown at the
end of this message) which can be compiled with:
% gfortran -g -fbacktrace main.F sub.F
Depending on the compiler version, the execution either correctly shows:
after init, rg2l_row(5001:5001)= 250
rg2l_row(5001)= 250
or, with gfortran 8.1 and 8.2, shows an erroneous value at the second line:
after init, rg2l_row(5001:5001)= 250
rg2l_row(5001)= 1000
Sometimes a SIGSEGV occurs. valgrind always reports an uninitialized
access when trying to access rg2l_row(5001), but rg2l_row(5001:5001) is
always ok. Pointer arithmetic to access element 5001 of rg2l_row thus
appears to be done differently depending on the expression used. Looking
at intermediate code, this might be related to the use of the "span"
component associated with the pointer array in one case and not the other.
When the first routine of sub.F (not used, not called) is suppressed
from that file, the problem disappears, indicating a side effect on the
way the compilation is done for the second routine when the derived type
has already been encountered in the file. Again looking at intermediate
code, it might be related to the initialization of the internal "span"
component associated with the rg2l_row pointer array.
A possible workaround, apart from compiling the two routines of sub.F
separately in two different files, consists in relying on a module for
the definition of the derived type.
However, it seems to me that the original example should also be
supported, and it was working fine with gfortran-7 and earlier. Could
this issue be related to the new support of parameterized derived types
in gfortran-8?
Hoping this feedback may be useful to gfortran.
Thanks for your work and best regards,
Jean-Yves
PS: below the 3 files to reproduce the issue
% cat main.F
PROGRAM GFORTRAN8_DERIVED_TYPE_BUG
IMPLICIT NONE
INCLUDE 'dmumps_root.h'
TYPE (DMUMPS_ROOT_STRUC) :: root
INTEGER :: I, N, INFO(2)
NULLIFY(root%RG2L_ROW)
NULLIFY(root%RG2L_COL)
N=10000; INFO=0
CALL DMUMPS_INIT_ROOT_FAC( N, root, INFO)
C Access to root%RG2L_ROW(5001:5001) works ok:
write(*,*) "after init, rg2l_row(5001:5001)=",
& root%RG2L_ROW(5001:5001)
C but access to root%RG2L_ROW(5001) fails:
C valgrind complains at next line which causes a SIGSEGV
C (accessed wrong memory address and returned wrong value
C in the original code).
C Everything is ok with earlier compiler versions
I = root%RG2L_ROW(5001)
WRITE(*,*) "rg2l_row(5001)=",I
END
% cat sub.F
C Uncoment #if 0 / #endif to make the code work with gfortran-8
c#if 0
SUBROUTINE DMUMPS_INIT_ROOT_ANA( N, root)
IMPLICIT NONE
INCLUDE 'dmumps_root.h'
TYPE (DMUMPS_ROOT_STRUC)::root
INTEGER :: N
root%ROOT_SIZE = 0
RETURN
END SUBROUTINE DMUMPS_INIT_ROOT_ANA
c#endif
SUBROUTINE DMUMPS_INIT_ROOT_FAC( N, root, INFO )
IMPLICIT NONE
INCLUDE 'dmumps_root.h'
TYPE ( DMUMPS_ROOT_STRUC ), target :: root
INTEGER N, INFO(2)
INTEGER I, allocok
ALLOCATE( root%RG2L_ROW( N ), stat = allocok )
IF ( allocok .GT. 0 ) THEN
INFO(1)=-13
INFO(2)=N
RETURN
ENDIF
ALLOCATE( root%RG2L_COL( N ), stat = allocok )
IF ( allocok .GT. 0 ) THEN
INFO(1)=-13
INFO(2)=N
RETURN
ENDIF
DO I=N, 1, -1
root%RG2L_ROW(I)=I*1000
root%RG2L_COL(I)=I*1000
ENDDO
root%RG2L_ROW(5001)=250
root%RG2L_COL(5001)=250
RETURN
END SUBROUTINE DMUMPS_INIT_ROOT_FAC
% cat dmumps_root.h
TYPE DMUMPS_ROOT_STRUC
SEQUENCE
INTEGER, DIMENSION(:), POINTER :: RG2L_ROW
INTEGER, DIMENSION(:), POINTER :: RG2L_COL
INTEGER :: ROOT_SIZE
END TYPE DMUMPS_ROOT_STRUC
I hope it is reasonable to report a gfortran problem at this address.
I have a tiny example showing a strange behaviour when accessing the
elements of a pointer array, which is part of a derived type. The
example consists of 3 files (main.F, sub.F, dmumps_root.h, shown at the
end of this message) which can be compiled with:
% gfortran -g -fbacktrace main.F sub.F
Depending on the compiler version, the execution either correctly shows:
after init, rg2l_row(5001:5001)= 250
rg2l_row(5001)= 250
or, with gfortran 8.1 and 8.2, shows an erroneous value at the second line:
after init, rg2l_row(5001:5001)= 250
rg2l_row(5001)= 1000
Sometimes a SIGSEGV occurs. valgrind always reports an uninitialized
access when trying to access rg2l_row(5001), but rg2l_row(5001:5001) is
always ok. Pointer arithmetic to access element 5001 of rg2l_row thus
appears to be done differently depending on the expression used. Looking
at intermediate code, this might be related to the use of the "span"
component associated with the pointer array in one case and not the other.
When the first routine of sub.F (not used, not called) is suppressed
from that file, the problem disappears, indicating a side effect on the
way the compilation is done for the second routine when the derived type
has already been encountered in the file. Again looking at intermediate
code, it might be related to the initialization of the internal "span"
component associated with the rg2l_row pointer array.
A possible workaround, apart from compiling the two routines of sub.F
separately in two different files, consists in relying on a module for
the definition of the derived type.
However, it seems to me that the original example should also be
supported, and it was working fine with gfortran-7 and earlier. Could
this issue be related to the new support of parameterized derived types
in gfortran-8?
Hoping this feedback may be useful to gfortran.
Thanks for your work and best regards,
Jean-Yves
PS: below the 3 files to reproduce the issue
% cat main.F
PROGRAM GFORTRAN8_DERIVED_TYPE_BUG
IMPLICIT NONE
INCLUDE 'dmumps_root.h'
TYPE (DMUMPS_ROOT_STRUC) :: root
INTEGER :: I, N, INFO(2)
NULLIFY(root%RG2L_ROW)
NULLIFY(root%RG2L_COL)
N=10000; INFO=0
CALL DMUMPS_INIT_ROOT_FAC( N, root, INFO)
C Access to root%RG2L_ROW(5001:5001) works ok:
write(*,*) "after init, rg2l_row(5001:5001)=",
& root%RG2L_ROW(5001:5001)
C but access to root%RG2L_ROW(5001) fails:
C valgrind complains at next line which causes a SIGSEGV
C (accessed wrong memory address and returned wrong value
C in the original code).
C Everything is ok with earlier compiler versions
I = root%RG2L_ROW(5001)
WRITE(*,*) "rg2l_row(5001)=",I
END
% cat sub.F
C Uncoment #if 0 / #endif to make the code work with gfortran-8
c#if 0
SUBROUTINE DMUMPS_INIT_ROOT_ANA( N, root)
IMPLICIT NONE
INCLUDE 'dmumps_root.h'
TYPE (DMUMPS_ROOT_STRUC)::root
INTEGER :: N
root%ROOT_SIZE = 0
RETURN
END SUBROUTINE DMUMPS_INIT_ROOT_ANA
c#endif
SUBROUTINE DMUMPS_INIT_ROOT_FAC( N, root, INFO )
IMPLICIT NONE
INCLUDE 'dmumps_root.h'
TYPE ( DMUMPS_ROOT_STRUC ), target :: root
INTEGER N, INFO(2)
INTEGER I, allocok
ALLOCATE( root%RG2L_ROW( N ), stat = allocok )
IF ( allocok .GT. 0 ) THEN
INFO(1)=-13
INFO(2)=N
RETURN
ENDIF
ALLOCATE( root%RG2L_COL( N ), stat = allocok )
IF ( allocok .GT. 0 ) THEN
INFO(1)=-13
INFO(2)=N
RETURN
ENDIF
DO I=N, 1, -1
root%RG2L_ROW(I)=I*1000
root%RG2L_COL(I)=I*1000
ENDDO
root%RG2L_ROW(5001)=250
root%RG2L_COL(5001)=250
RETURN
END SUBROUTINE DMUMPS_INIT_ROOT_FAC
% cat dmumps_root.h
TYPE DMUMPS_ROOT_STRUC
SEQUENCE
INTEGER, DIMENSION(:), POINTER :: RG2L_ROW
INTEGER, DIMENSION(:), POINTER :: RG2L_COL
INTEGER :: ROOT_SIZE
END TYPE DMUMPS_ROOT_STRUC