Я разрабатываю объектно-ориентированный код Fortran для численной оптимизации с полиморфизмом, поддерживаемый абстрактными типами. Поскольку это хорошая практика TDD, я пытаюсь написать все тесты оптимизации в абстрактном типе class(generic_optimizer)
, который затем должен запускаться каждым экземпляром класса, например, на type(newton_raphson)
.Ошибка сегментации с отложенными функциями и ключевое слово non_overridable
Все тесты оптимизации содержат вызов call my_problem%solve(...)
, который определяется как абстрактный тип и, конечно же, имеет различную реализацию в каждом производном типе.
Вопрос: если в каждом неабстрактном классе я определить функцию отложенной в 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' запрещен (и более поздняя попытка переопределить). Однако у меня нет доступа к компилятору, чтобы воспроизвести проблему. – francescalus
Похож на ошибку компилятора. – IanH
Что это связано с Отсрочкой? –