Funções do ponteiro Fortran:por que o comportamento desse código depende da ordem das chamadas de função?
Pergunta
Contexto
O código Fortran de brinquedo postado abaixo chama duas funções de ponteiro.Ou seja, ambas as funções retornam um ponteiro.Na verdade, ambos são ponteiros de array.Ambos tentam fazer a mesma coisa, que é retornar um ponteiro de array inteiro referenciando um array inteiro com três elementos, 1, 2 e 3.A primeira função usa o operador de atribuição de ponteiro (=>) para apontar o ponteiro da função para uma matriz alocável que contém os dados.A segunda função aloca um bloco de memória dinâmica diretamente, através do ponteiro, para armazenar os dados.O programa de chamada apenas imprime os elementos do(s) array(s) retornado(s).
Aqui está o que acho estranho.
- Se eu apontar
a
ao resultado defunction1
, os resultados não estão corretos.O primeiro elementoa
parece estar "derrotado":a
tem0
,2
,3
. - Se eu apontar
b
ao resultado defunction2
, os resultados estão corretos.b
recebe1
,2
,3
. - Mais estranho ainda, apontando
b
ao resultado defunction2
depois apontandoa
parafunction1
mudançasa
tal que se torne correto.a
então tem1
,2
,3
.
Pergunta
Por que isso ocorre?Mais precisamente, por que uma função de ponteiro que retorna um ponteiro para um array alocável supera o primeiro elemento desse array para o chamador?Mais precisamente ainda, por que apontar um ponteiro (b
) produzem um efeito colateral em outro ponteiro (a
), onde os alvos vêm de funções diferentes que são escritas de forma a não interagirem entre si?
Ressalvas
Recebo esse comportamento usando o compilador GNU Fortran v.4.3.3, executando um laptop Intel com Ubuntu (Jaunty).Seus resultados podem variar, o que pode ser ainda mais interessante.Finalmente, como sempre, pode ser um erro do operador da minha parte, o que seria interessante para mim, pelo menos.
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
Solução
Variável variedade de function1 é uma variável local - porque é declarada sem o atributo "save", não é persistente e é indefinida quando a função é encerrada.Você atribui o endereço de variedade para function1, "mantendo" este endereço, mas o endereço não é significativo quando a variável se torna indefinida após sair da função.Uma implementação provável é que variedade da função1 será colocada na pilha e essa área da pilha será liberada para outros usos quando a função1 retornar.Mas isso é apenas um palpite sobre uma implementação provável - o ponto principal é que você não tem permissão para usar o valor do ponteiro depois que a variável se torna indefinida.Variáveis alocáveis são automaticamente desalocadas quando saem do escopo, a menos que você as declare com o atributo "save".