Неправильная длина компонента символьного массива после выделения - PullRequest
2 голосов
/ 11 февраля 2020

Я хотел бы создать производный тип, содержащий размещаемые компоненты массива символов. Однако, когда я пытаюсь выделить память в подпрограммах, ничего не происходит. Это может быть более понятно с примером кода ниже:

program test

  type t1
     character(len=:), allocatable :: c(:)
  end type t1

  type(t1) :: t

  call test_string1()
  call test_string2(t)

contains

  subroutine test_string1()
    character(len=:), allocatable :: c(:)

    allocate( character(10) :: c(1) )
    write(*, *) 'Size in string1: ', len(c)
  end subroutine test_string1


  subroutine test_string2(this)
    class(t1) :: this

    allocate( character(10) :: this%c(1) )
    write(*, *) 'Size in string2: ', len(this%c)
  end subroutine test_string2


end program test

Я ожидаю, что вывод такого кода будет:

 Size in string1:           10
 Size in string2:           10

Однако, что я на самом деле получаю, это следующее :

 Size in string1:           10
 Size in string2:            0

Поэтому вторая подпрограмма ничего не выделяет для t1%c ... Что я здесь не так делаю? Я скомпилировал код с:

gfortran -c test.f08
gfortran -o test test.o

и версия gfortran выглядит следующим образом:

$ gfortran -v
...
gcc version 7.4.0 (Ubuntu 7.4.0-1ubuntu1~18.04.1)

1 Ответ

1 голос
/ 11 февраля 2020

Это ошибка (или отсутствие поддержки) в используемой версии компилятора. В версиях gfortran 7 и 8 я вижу ту же проблему, но, как уже было отмечено, gfortran 9 дает ожидаемый ответ. «Использовать другой компилятор / версию» - это ответ на ваш вопрос.

Что иногда полезно в подобных случаях, так это дополнительный вопрос: «Что я могу сделать, чтобы обойти эту ошибку, не меняя компилятор?»

Пример вопроса довольно прост, что приводит к небольшому количеству вариантов. Внутреннее c присваивание построенного массива или распределение по источникам не помогают.

Есть что-нибудь интересное, что делает? Почему да! Параметризованные производные типы.

Похоже, что gfortran 8 сталкивается с проблемой вопроса, но поддерживает параметризацию производного типа (gfortran 7 не поддерживает эту функцию Fortran 2003). Это может быть хороший обходной путь или даже альтернативный подход к реальной проблеме:

program test

  type t1(length, size)
     integer, len :: length, size
     character(len=length) :: c(size)
  end type t1

  class(t1(:,:)), allocatable :: t

  call test_string1()
  call test_string2(t)

contains

  subroutine test_string1()
    character(len=:), allocatable :: c(:)

    allocate( character(10) :: c(1) )
    write(*, *) 'Size in string1: ', len(c)
  end subroutine test_string1


  subroutine test_string2(this)
    class(t1(:,:)), allocatable :: this

    allocate( t1(10,1) :: this )
    write(*, *) 'Size in string2: ', len(this%c)
  end subroutine test_string2


end program test
...