Funciones del puntero Fortran:¿Por qué el comportamiento de este código depende del orden de las llamadas a funciones?
Pregunta
Contexto
El código Fortran de juguete publicado a continuación llama a dos funciones de puntero.Es decir, ambas funciones devuelven un puntero.De hecho, ambos son punteros de matriz.Ambos intentan hacer lo mismo, que es devolver un puntero de matriz de enteros que hace referencia a una matriz de enteros que tiene tres elementos, 1, 2 y 3.La primera función utiliza el operador de asignación de puntero (=>) para apuntar el puntero de la función a una matriz asignable que contiene los datos.La segunda función asigna un bloque de memoria dinámica directamente, a través del puntero, para almacenar los datos.El programa que llama simplemente imprime los elementos de las matrices devueltas.
Esto es lo que me parece extraño.
- si señalo
a
al resultado defunction1
, los resultados no son correctos.El primer elemento dea
parece estar "golpeado":a
tiene0
,2
,3
. - si señalo
b
al resultado defunction2
, los resultados son correctos.b
obtiene1
,2
,3
. - Más extraño aún, señalando
b
al resultado defunction2
después apuntandoa
afunction1
cambiosa
tal que sea correcto.a
entonces tiene1
,2
,3
.
Pregunta
¿Por qué ocurre esto?Más precisamente, ¿por qué una función de puntero que devuelve un puntero a una matriz asignable golpea el primer elemento de esa matriz para la persona que llama?Más precisamente aún, ¿por qué apuntar con un puntero (b
) producir un efecto secundario en otro puntero (a
), donde los objetivos provienen de diferentes funciones que están escritas para no interactuar entre sí en absoluto?
Advertencias
Obtengo este comportamiento usando el compilador GNU Fortran v.4.3.3, ejecutando una computadora portátil Intel con Ubuntu (Jaunty).Sus resultados pueden variar, lo que podría ser aún más interesante.Finalmente, como siempre, podría ser un error del operador por mi parte, lo cual al menos sería interesante para mí.
Código
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
Solución
Variable array de function1 es una variable local - porque se ha declarado sin el "Guardar" atributo, no es persistente y no está definida cuando se cierra la función. Se asigna la dirección de array a function1, "mantener" esta dirección, pero la dirección no es significativa una vez que la variable se convierte en indefinido después de salir de la función. Una aplicación posible es que array de function1 se colocará en la pila, y esa zona de la pila será liberado para otros usos cuando se devuelve FUNCTION1. Pero esto es sólo una conjetura en una implementación probable - el punto clave es que usted no está autorizado a utilizar el valor del puntero después de la variable se convierte en indefinido. las variables asignables se cancela la asignación automática cuando salen del ámbito menos que se declaran con la opción "Guardar" atributo.