Является ли присвоение векторной функции atomi c? (Не могу понять ошибку) - PullRequest
1 голос
/ 16 апреля 2020

У меня ошибка сегментации из программы, и я понимаю, что что-то не так, потому что я использую аргумент, который не выделен, но я не совсем понимаю внутреннюю работу ошибки:

program MWE
      implicit none

      integer, allocatable :: b(:)

      call S(b)

      contains

      subroutine S(a)
              integer, intent(out) :: a(:)
              a = F(10) !I was expecting the error here
              ! but in the assigment not inside
              ! the function call.
      end subroutine

      function F(n) result(v)
              integer, intent(in) :: n
              integer :: v(n)
              print*, "Now comes the error"
              v = 1 !here, in this assignment
              print*, "We nevet get here"
      end function
end program


Я понимаю, что я объявляю переменную a как , которую можно выделить , и я знаю, что передаю ее подпрограмме S без ее выделения.

Однако я ожидал бы, что функция F будет работать нормально, так как она задана N и, таким образом, она знает размер v . Я ожидал, что ошибка сегментации появится после завершения F , но до присвоения его выхода a .

Учитывая, что я получаю ошибку внутри функции F Я неправильно понимаю некоторую внутреннюю работу, но я не знаю что.

Это результат выполнения:

Now comes the error

Program received signal SIGSEGV: Segmentation fault - invalid memory reference.

Backtrace for this error:
#0  0x7f1bff9f28b0 in ???
#1  0x7f1bff9f1ae3 in ???
#2  0x7f1bff66c83f in ???
    at /build/glibc-vjB4T1/glibc-2.28/signal/../sysdeps/unix/sysv/linux/x86_64/sigaction.c:0
#3  0x562fc494c262 in ???
#4  0x562fc494c3d3 in ???
#5  0x562fc494c30b in ???
#6  0x562fc494c40c in ???
#7  0x7f1bff65909a in __libc_start_main
    at ../csu/libc-start.c:308
#8  0x562fc494c0b9 in ???
#9  0xffffffffffffffff in ???
Segmentation fault

1 Ответ

2 голосов
/ 16 апреля 2020

Для этого вызова функции gfortran передает скрытый аргумент функции, который сообщает функции, где в памяти она должна поместить результат функции. Этот скрытый аргумент определяет хранилище, связанное с фиктивным аргументом a в подпрограмме. Это хранилище недопустимо, потому что фактический аргумент, связанный с фиктивным a, не был выделен, поэтому хранилище, в которое функция пытается поместить свой результат, недопустимо, поэтому вы видите нарушение доступа внутри функции.

Действие, связанное с оператором присваивания, подразумевается при получении функции записи непосредственно в хранилище объекта в левой части присваивания.

Различные компиляторы (или один и тот же компилятор для вызова функции или оператор присваивания с другими характеристиками) будет реализовывать это по-разному - например, функция может записывать во временное состояние, которое вызывающий код устанавливает и затем копирует, или внутри функции может быть выделен буфер, в котором затем нуждается вызывающий код к выпуску.

Вы можете проверить, как компилятор gfortran реализует вашу программу, проверив сборку (добавьте -S в командную строку) или одно из промежуточных представлений (например, -fdump-tree). ПЕРВОНАЧАЛЬНО)

...