Функции указателя Fortran:почему поведение этого кода зависит от порядка вызовов функций?

StackOverflow https://stackoverflow.com/questions/1580426

Вопрос

Контекст

Игрушечный код Fortran, размещенный ниже, вызывает две функции указателя.То есть обе функции возвращают указатель.Фактически, они оба являются указателями на массив.Они оба пытаются сделать одно и то же, а именно вернуть указатель на целочисленный массив, ссылающийся на целочисленный массив, содержащий три элемента: 1, 2 и 3.Первая функция использует оператор присваивания указателя (=>), чтобы указать указатель функции на выделяемый массив, содержащий данные.Вторая функция выделяет блок динамической памяти непосредственно, через указатель, для хранения данных.Вызывающая программа просто печатает элементы возвращаемого массива (ов).

Вот что я нахожу странным.

  1. Если я укажу a к результату function1, результаты неверны.Первый элемент a кажется, его "побили".: a имеет 0, 2, 3.
  2. Если я укажу b к результату function2, результаты верны. b получает 1, 2, 3.
  3. Еще более странный, указывающий b к результату function2 после указывающий a Для function1 Изменения a таким образом, чтобы это стало правильным. a затем имеет 1, 2, 3.

Вопрос

Почему это происходит?Точнее, почему функция-указатель, которая возвращает указатель на выделяемый массив, блокирует первый элемент этого массива для вызывающего?Еще точнее, почему указывает на один указатель (b) создает побочный эффект для другого указателя (a), где цели исходят из разных функций, которые написаны так, чтобы вообще не взаимодействовать друг с другом?

Предостережения

Я получаю это поведение, используя компилятор GNU Fortran v.4.3.3, работающий на ноутбуке Intel с Ubuntu (Jaunty).Ваши результаты могут отличаться, что может быть еще интереснее.Наконец, как всегда, это может быть ошибка оператора с моей стороны, что было бы интересно, по крайней мере, мне.

Код

program main
  implicit none
  integer, dimension(:), pointer :: a, b
  integer :: i
  a => function1()
  b => function2()
  do i = 1, 3
     print *, a(i)
  end do
  ! do i = 1, 3
  !    print *, b(i)
  ! end do
contains
  function function1 ()
    integer, dimension(:), allocatable, target :: array
    integer, dimension(:), pointer :: function1
    allocate(array(3))
    array(1) = 1
    array(2) = 2
    array(3) = 3
    function1 => array
  end function function1

  function function2 ()
    integer, dimension(:), pointer :: function2
    allocate(function2(3))
    function2(1) = 1
    function2(2) = 2
    function2(3) = 3
  end function function2
end program main
Это было полезно?

Решение

Переменная массив of function1 является локальной переменной - поскольку она объявлена без атрибута "сохранить", она не является постоянной и не определена при завершении функции.Вы назначаете адрес массив к function1, "сохраняя" этот адрес, но адрес не имеет смысла, как только переменная становится неопределенной после выхода из функции.Вероятная реализация заключается в том, что массив of function1 будет помещен в стек, и эта область стека будет освобождена для других целей, когда function1 вернется.Но это всего лишь предположение о вероятной реализации - ключевым моментом является то, что вам не разрешается использовать значение указателя после того, как переменная становится неопределенной.Выделяемые переменные автоматически освобождаются, когда они выходят за пределы области видимости, если только вы не объявите их с атрибутом "сохранить".

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top