Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/oop/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/fortran/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Oop Fortran面向对象中的不确定性行为,带有延迟和不可重写过程以及gcc编译器_Oop_Fortran_Abstract Class_Gfortran - Fatal编程技术网

Oop Fortran面向对象中的不确定性行为,带有延迟和不可重写过程以及gcc编译器

Oop Fortran面向对象中的不确定性行为,带有延迟和不可重写过程以及gcc编译器,oop,fortran,abstract-class,gfortran,Oop,Fortran,Abstract Class,Gfortran,我构建了一个简单的案例来重现下面的问题。我不能再减少了。 问题描述: 我有三节课 A、 模块A_Mod(A_Mod.f90)中的抽象类,带有延迟过程cleanup B、 在模块B_Mod(B_Mod.f90)中扩展A的抽象类。B执行延迟过程清理,定义并执行以下过程:初始化、完成,并定义以下延迟过程:设置、释放资源、重置 C、 在模块C_Mod(C_Mod.f90)中扩展B,并执行延迟过程设置、释放资源、重置 定义变量(C型对象)的测试程序(test.f90),调用init,然后对对象执行fi

我构建了一个简单的案例来重现下面的问题。我不能再减少了。 问题描述: 我有三节课

  • A、 模块A_Mod(A_Mod.f90)中的抽象类,带有延迟过程
    cleanup
  • B、 在模块B_Mod(B_Mod.f90)中扩展A的抽象类。B执行延迟过程
    清理
    ,定义并执行以下过程:
    初始化、完成
    ,并定义以下延迟过程:
    设置、释放资源、重置
  • C、 在模块C_Mod(C_Mod.f90)中扩展B,并执行延迟过程
    设置、释放资源、重置
定义变量(C型对象)的测试程序(test.f90),调用
init
,然后对对象执行
finalize
过程

源代码中调用的过程似乎不是可执行文件中调用(运行)的过程:子例程调用在编译时出错。在类
B
的过程
init
上删除
non_overridable
之类的小更改(使用gfortran 7.5.0)会产生一个无限循环调用
init
(就像init和setup指向同一过程一样)。这种循环行为可以通过代码中的其他一些小更改来重现

我怀疑问题与
延迟的
不可重写的
有关。除非我犯了错误,否则它看起来像是4.8.5之后引入的gfortran中的一个bug

预期产出:

Test: calling C%init
  B::init, calling setup
    C::setup
  B::init done ...............
Test: calling C%finalize
  B::finalize, calling free_resources
    C::free_resources
  B::finalize, calling cleanup
  B::cleanup
  B::finalize done ...................
Test:done.......................
我得到的是:

Test: calling C%init
  B::init, calling setup
  B::cleanup
  B::init done ...............
Test: calling C%finalize
  B::finalize, calling free_resources
    C::setup
  B::finalize, calling cleanup
  B::cleanup
  B::finalize done ...................
Test:done.......................
我尝试了以下版本的gfortran:

  • ifort 19.0.5.281=>预期结果
  • ifort 19.0.4.243=>预期结果
  • ifort 19.0.2.187=>预期结果
  • ifort 18.0.1=>预期结果
  • ifort 17.0.4=>预期结果
  • GNU Fortran(GCC)4.8.5=>预期结果
  • GNU Fortran(GCC)6.3.0=>错误的结果(与其他略有不同,请参见下文)
  • GNU Fortran(GCC)7.5.0=>错误结果
  • GNU Fortran(GCC)8.4.0=>错误结果
  • GNU Fortran(GCC)9.2.0=>错误的结果
  • GNU Fortran(GCC)8.2.0=>错误结果
  • GNU Fortran(GCC)7.3.0=>错误结果
gfortran 6的结果(请参阅调用重置)

源代码:

$ cat A_Mod.f90

这似乎是当前gfortran(9.3)中的一个错误。它需要非常具体的环境,包括在单独的文件中包含模块的源代码


如果你想解决这个bug,最好通过普通的gcc bug报告渠道()进行报告。

我猜问题是“这是一个编译器bug吗”?@IanH,在我看来像是一个编译器bug!那么,你打算向开发人员报告这个bug吗?我刚刚报告:它是6.3.0版之后的bug,可能是之前的版本。4.8.5产生预期结果。
$ cat A_Mod.f90
    !
    module A_Mod
    implicit none
        !
        private
        !
        type, public, abstract :: A
            private
            logical :: status !< status of the object
        contains
            !   
            procedure, non_overridable :: setStatus
            procedure :: unsetStatus
            !
            procedure( cleanup ), deferred :: cleanup
            !procedure, nopass :: do_nothing
        end type A
        !
        interface cleanup
            !
            subroutine cleanup(this)
                import A
                class(A), intent(in out) :: this
            end subroutine cleanup
        end interface cleanup
        !
    contains
        !
        subroutine setStatus(this)
            class(A), intent(in out) :: this
            !
            this%status = .true.
        end subroutine setStatus
        !
        subroutine unsetStatus(this)
            class(A), intent(in out) :: this
            !
            this%status = .false.
        end subroutine unsetStatus
    !     !
    !     subroutine do_nothing()
    !     end subroutine do_nothing
        !
    end module A_Mod
cat B_Mod.f90
!
    module B_Mod
        !
        use A_Mod
    implicit none
        !
        private
        integer, private, parameter :: version = 0
        !
        type, public, abstract, extends(A) :: B
            integer :: action
        contains
            !
            procedure (free_resources), deferred :: free_resources
            procedure (reset), deferred :: reset
            procedure (setup), deferred :: setup
            !
            procedure, non_overridable :: init
            !
            ! Procedures from A
            procedure, non_overridable :: finalize
            procedure, non_overridable :: cleanup
            !
        end type B
        !
        interface
            !
            subroutine free_resources( this )
                import B
                class(B), intent(in out) :: this
                !
            end subroutine free_resources
            !
            subroutine reset( this )
                import B
                class( B ), intent(in out) :: this
            end subroutine reset
            !
            subroutine setup( this )
                import B
                class(B), intent(in out) :: this
                !
            end subroutine setup
            !
        end interface
        !
    contains
        !
        subroutine init( this )
            class(B), intent(in out) :: this
            !
            write(*,"('  B::init, calling setup')")
            call this%setup()
            write(*,"('  B::init done ...............')")
            this%action=1
            !
        end subroutine init
        !
        subroutine finalize( this )
            class(B), intent(in out) :: this
            !
            write(*,"('  B::finalize, calling free_resources')")
            call this%free_resources(  )
            write(*,"('  B::finalize, calling cleanup')")
            call this%cleanup()
            write(*,"('  B::finalize done ...................')")
            this%action=0
            !
        end subroutine finalize
        !
        subroutine cleanup( this )
            class(B), intent(in out) :: this
            !
            !call this%do_nothing()
            write(*,"('  B::cleanup')")
            !call this%reset()
            this%action=-1
            !
        end subroutine cleanup
        !
    end module B_Mod
$ cat C_Mod.f90
!
module C_Mod
    !
    use B_Mod
    !
implicit none
    !
    private
    !
    type, public, extends(B) :: C
        !integer :: n
    contains
        ! From B
        procedure :: free_resources
        procedure :: reset
        procedure :: setup
        !
    end type C
    !
contains
    !
    subroutine setup( this )
        class(C), intent(in out) :: this
        !
        !call this%do_nothing()
        write(*,"('    C::setup')")
        !
    end subroutine setup
    !
    subroutine free_resources( this )
        class(C), intent(in out) :: this
        !
        !call this%do_nothing()
        write(*,"('    C::free_resources')")
        !
    end subroutine free_resources
    !
    subroutine reset(this)
        class(C), intent(in out) :: this
        !
        !call this%do_nothing()
        write(*,"('    C::reset')")
        !
    end subroutine reset
    !
end module C_Mod
$ cat test.f90
!> @file test.f90
!! to test the basic functionalities of the framework
!<

!> @brief test program
!!
!<
program test
    use C_Mod
implicit none
    !
    !
    call test_grid1d()
    !
contains
    !
    subroutine test_grid1d()
        type(C) :: c1
        !
        write(*,"('Test: calling C%init')")
        call c1%init()
        write(*,"('Test: calling C%finalize')")
        call c1%finalize()
        write(*,"('Test:done.......................')")
        !
    end subroutine test_grid1d
    !
end program test
COMPILE=gfortran -g
LINK=gfortran
${COMPILE} A_Mod.f90 -o A_Mod.o
${COMPILE} B_Mod.f90 -o B_Mod.o
${COMPILE} C_Mod.f90 -o C_Mod.o
${COMPILE} test.f90  -o test.o

${LINK} -o  test A_Mod.o  B_Mod.o C_Mod.o test.o
./test