【发布时间】:2017-03-23 11:12:45
【问题描述】:
我正在开发一个面向对象的 Fortran 代码,用于通过抽象类型支持的多态性进行数值优化。因为这是一个很好的 TDD 实践,所以我尝试在抽象类型 class(generic_optimizer) 中编写所有优化测试,然后应该由每个实例化类运行,例如 type(newton_raphson)。
所有优化测试都调用call my_problem%solve(...),在抽象类型中定义为deferred,当然每个派生类型都有不同的实现。
问题是:如果在每个非抽象类中我将延迟函数定义为non_overridable,则会出现分段错误,例如:
Program received signal SIGSEGV, Segmentation fault.
0x0000000000000000 in ?? ()
(gdb) where
#0 0x0000000000000000 in ?? ()
#1 0x0000000000913efe in __newton_raphson_MOD_nr_solve ()
#2 0x00000000008cfafa in MAIN__ ()
#3 0x00000000008cfb2b in main ()
#4 0x0000003a3c81ed5d in __libc_start_main () from /lib64/libc.so.6
#5 0x00000000004048f9 in _start ()
经过反复试验,我注意到如果删除 non_overridable 声明,我可以避免该错误。在这种情况下,这不是问题,但我想强制执行这一点,因为此代码不太可能存在两级多态性。我是否违反了标准中的任何要求?
这里是重现错误的示例代码。我一直在使用 gfortran 5.3.0 和 6.1.0 对其进行测试。
module generic_type_module
implicit none
private
type, abstract, public :: generic_type
real(8) :: some_data
contains
procedure (sqrt_interface), deferred :: square_root
procedure, non_overridable :: sqrt_test
end type generic_type
abstract interface
real(8) function sqrt_interface(this,x) result(sqrtx)
import generic_type
class(generic_type), intent(in) :: this
real(8), intent(in) :: x
end function sqrt_interface
end interface
contains
subroutine sqrt_test(this,x)
class(generic_type), intent(in) :: this
real(8), intent(in) :: x
print *, 'sqrt(',x,') = ',this%square_root(x)
end subroutine sqrt_test
end module generic_type_module
module actual_types_module
use generic_type_module
implicit none
private
type, public, extends(generic_type) :: crashing
real(8) :: other_data
contains
procedure, non_overridable :: square_root => crashing_square_root
end type crashing
type, public, extends(generic_type) :: working
real(8) :: other_data
contains
procedure :: square_root => working_square_root
end type working
contains
real(8) function crashing_square_root(this,x) result(sqrtx)
class(crashing), intent(in) :: this
real(8), intent(in) :: x
sqrtx = sqrt(x)
end function crashing_square_root
real(8) function working_square_root(this,x) result(sqrtx)
class(working), intent(in) :: this
real(8), intent(in) :: x
sqrtx = sqrt(x)
end function working_square_root
end module actual_types_module
program deferred_test
use actual_types_module
implicit none
type(crashing) :: crashes
type(working) :: works
call works%sqrt_test(2.0_8)
call crashes%sqrt_test(2.0_8)
end program
【问题讨论】:
-
快速浏览一下,没有明显的理由禁止
non_overridable属性(以后也不会尝试覆盖)。不过,我无权使用编译器来重现该问题。 -
在我看来像一个编译器错误。
-
这与 Deferreds 有什么关系?
-
请不要在写得很好的代码中使用
real(8),它真的很难看。 stackoverflow.com/documentation/fortran/939/data-types/4390/… -
谢谢你们的意见 - 看起来这是次要问题,但你认为我应该在 GCC bugzilla 上开一张票吗?
标签: oop fortran fortran2003 fortran2008