Столкновение между назначением копирования и конструктором в Фортране - PullRequest
1 голос
/ 07 апреля 2019

У меня есть следующий код, который вызывает ошибку сегментации.Он жалуется, что

forrtl: суровый (408): форт: (7): Попытка использовать указатель TT, когда он не связан с целью

Теперь яЯ почти уверен, в чем причина, а именно, он пытается получить доступ к моей подпрограмме copy, в то время как я просто пытаюсь инициализировать объект.

Закомментировав generic :: assignment(=) => copy, он работает отлично!

Я компилирую код следующим образом: (IFORT версия 19.0.3) ifort -O0 -debug full -check all -traceback -g -C -CB -CU -CA -fpp filaname.f90 и выполняется ./a.out

   module md

   implicit none

   type T_TEST

      integer :: ii

   contains
         procedure, pass(this)               :: COPY
       generic :: assignment(=) => copy

   end type


   interface t_test
      module procedure init
   end interface t_test


   type(t_test) , allocatable :: tt


contains
   function init( size )
      integer, intent(in)                   :: size
      type(t_test) , allocatable           :: init


      allocate( init )
      init% ii = size
   end function

   subroutine copy(this, old )

      class(t_test), intent(out)  ::this
      type(t_test), intent(in) :: old


       this% ii = old% ii

   end subroutine

end module md

program t_Testprogram
use md
implicit none

tt = t_test( 100 )

end program t_Testprogram

1 Ответ

3 голосов
/ 07 апреля 2019

Причина в том, что перегруженное присваивание copy не поддерживает выделяемые левые части.Поэтому, когда значение this используется в this% ii = old% ii, оно фактически не существует и используется нулевой указатель.Но я согласен с тем, что сообщение об ошибке Intel сбивает с толку или даже неверно.

Автоматическое левостороннее (пере) распределение применяется только для внутренних назначений, а не для определенных пользователем.В определенных пользователем вы должны запрограммировать себя точное поведение.И вы ничего не указали для нераспределенных левых частей.

Это работает для меня:

   type T_TEST

      integer :: ii

   end type


   interface assignment(=)
     procedure copy
   end interface


   subroutine copy(this, old )

      class(t_test), allocatable, intent(out)  ::this
      type(t_test), intent(in) :: old

       if (.not.allocated(this)) allocate(this)
       this% ii = old% ii

   end subroutine

Или вы можете просто выделить объект первым (, это то, что ябудет делать здесь, потому что gfortran, похоже, не нравится общее разрешение на основе выделяемого атрибута - функции F08.

allocate(tt)
tt = t_test( 100 )

Кажется, что вы думаете, что только потому, что конструктор имеет егопеременная результата «помечена» allocatable, она выделит вам левую часть задания.Это не так .Единственное, что он делает, это то, что он выделяет свой собственный результат как временную переменную.Этот результат затем присваивается в tt = t_test(), а затем автоматически освобождается.

Помните, что переменная результата не такая же, как левая часть присвоения.Результат может использоваться в выражении разных типов, а не только в присваивании.Это может быть передано подпрограмме, это может быть использовано в арифметическом выражении, оно может быть напечатано ...

Ваш конструктор может быть просто

   function init( size )
      integer, intent(in)                   :: size
      type(t_test)           :: init

      init% ii = size
   end function

, и результат будет точнотот же самый.Нет причин делать это размещаемым, это только усложняет, но не меняет результат ни в малейшей степени.

Может быть, то, что вы пытаетесь следовать некоторым принципам C ++ RAII, но помните, C ++ просто не Fortran.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...