Функции указателя Fortran:почему поведение этого кода зависит от порядка вызовов функций?
Вопрос
Контекст
Игрушечный код Fortran, размещенный ниже, вызывает две функции указателя.То есть обе функции возвращают указатель.Фактически, они оба являются указателями на массив.Они оба пытаются сделать одно и то же, а именно вернуть указатель на целочисленный массив, ссылающийся на целочисленный массив, содержащий три элемента: 1, 2 и 3.Первая функция использует оператор присваивания указателя (=>), чтобы указать указатель функции на выделяемый массив, содержащий данные.Вторая функция выделяет блок динамической памяти непосредственно, через указатель, для хранения данных.Вызывающая программа просто печатает элементы возвращаемого массива (ов).
Вот что я нахожу странным.
- Если я укажу
a
к результатуfunction1
, результаты неверны.Первый элементa
кажется, его "побили".:a
имеет0
,2
,3
. - Если я укажу
b
к результатуfunction2
, результаты верны.b
получает1
,2
,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 вернется.Но это всего лишь предположение о вероятной реализации - ключевым моментом является то, что вам не разрешается использовать значение указателя после того, как переменная становится неопределенной.Выделяемые переменные автоматически освобождаются, когда они выходят за пределы области видимости, если только вы не объявите их с атрибутом "сохранить".