gfortran指针程序类型问题

时间:2018-05-16 11:29:11

标签: fortran gfortran

我尝试使用一个可以接受不同输入类型而不使用通用过程的过程。实际上,(在这种情况下)我更喜欢手动设置过程指针的目标来定义要使用的过程而不是通用过程。

这就是我用以下几乎最小的例子做的事情。

module mo
implicit none

type :: TypeB
    character(len=5) :: info='Hello'
    contains
    procedure,  pass(fd) :: say_hello 
end type TypeB

type :: TypeA
    character(len=4) :: txt='Hola'
    !type(TypeB) :: Tb
end type TypeA

type, extends(TypeA) :: TypeC
    character(len=4) :: tt='Hey!'
    type(TypeB) :: Tb
end type TypeC

type, extends(TypeA) :: TypeD
    character(len=3) :: tt='Ho!'
    character(len=3) :: ti='you'
    !type(TypeB) :: Tb
end type TypeD

type(TypeC) :: Tc
type(TypeD) :: Td
procedure(), pointer :: proc
class(TypeA), allocatable :: CA


contains

subroutine say_hello(fd)
    implicit none
    ! type(TypeB), intent(inout) :: fd
    class(TypeB), intent(inout) :: fd

    print *, fd%info

end subroutine say_hello

subroutine procC(fd, args)
    implicit none
    ! class(TypeC), intent(inout) :: fd
    type(TypeC), intent(inout) :: fd
    real :: args

    print*, args
    print*, fd%tt
    call fd%Tb%say_hello()
end subroutine procC

subroutine procD(fd, args)
    implicit none
    ! class(TypeD), intent(inout) :: fd
    type(TypeD), intent(inout) :: fd
    ! class(TypeA), intent(inout) :: fd
    real :: args

    print*, args
    print*, fd%tt
    print*, fd%ti
end subroutine procD

end module mo


program p
    use mo
    implicit none

    print* , 'START'
    print *, Tc%tb%info
    print *, Tc%txt
    call Tc%Tb%say_hello()
    call procC(Tc, 1.0)
    call procD(Td, 2.0)
    print*, 'OK'

    allocate(TypeD :: CA)
    proc =>procD
    call proc(CA, 3.0)
    deallocate(CA)

    allocate(TypeC :: CA)
    proc =>procC
    call proc(CA, 4.0)
    deallocate(CA)

    print*, 'END'

end program p

当我在Linux上使用ifort编译但是当我在Windows或Linux(gfortran 5.5.0和6.4.0)上使用gfortran(MinGW 6.2.0)编译时,我得到了预期的结果,我得到一些奇怪的东西:

START
Hello
Hola
Hello
1.00000000
Hey!
Hello
2.00000000
Ho!
you
OK
3.00000000

@R
4.00000000

ÇR@
END

当我在我的大程序中使用此方法时出现分段错误,事情变得越来越糟。

那么,有没有办法避免这些问题?这是gfortran的错误吗?或者我误解了什么?

1 个答案:

答案 0 :(得分:1)

你的程序有问题。

考虑

部分
proc =>procD
call proc(CA, 3.0)

我首先会考虑

call procD(CA,3.0)

子例程procD具有声明为type(typeD)的第一个伪参数。这是一个非多态实体,具有动态和声明类型typeD。主程序的实际参数CA是动态类型typeD的多态实体,但声明类型为typeA

在过程引用中,每个伪参数都必须与与之关联的实际参数类型兼容。这不是这里的情况:非多态对象仅与与其自身具有相同声明类型的实体类型兼容。它与多态实体不兼容,而且同一动态类型的声明类型不同。

在工作版

call procD(Td, 2.0)

实际参数Td属于声明类型typeD,因此类型兼容。

在此处使用带有隐式接口的过程指针会使编译器更难在程序中检测到此错误(不需要这样做)。