funzioni di puntatore Fortran: perché il comportamento di questo codice dipendono dall'ordine di chiamate di funzione?
Domanda
Contesto
Il codice Fortran giocattolo postato qui sotto chiama due funzioni di puntatore. Cioè, entrambe le funzioni restituiscono un puntatore. In realtà, sono entrambi puntatori array. Entrambi tentativo di fare la stessa cosa, che è quello di restituire un puntatore integer referenziare un array intero avente tre elementi, 1, 2, e 3. La prima funzione utilizza l'operatore di assegnazione puntatore (=>) per puntare il puntatore alla funzione di un array allocatable che contiene i dati. La seconda funzione alloca un blocco di memoria dinamica direttamente, tramite il puntatore, per la memorizzazione dei dati. Il programma chiamante si limita a stampare gli elementi dell'array restituito (s).
Ecco quello che trovo strano.
- Se io punto
a
al risultato difunction1
, i risultati non sono corretti. Il primo elemento dia
sembra essere "rovinati":.a
ha0
,2
,3
- Se io punto
b
al risultato difunction2
, i risultati sono corretti.b
ottiene1
,2
,3
. - Peggio ancora, indicando
b
al risultato difunction2
dopo che puntaa
afunction1
modifichea
tale che diventa corretto.a
ha poi1
,2
,3
.
Domanda
Perché si verifica? Più precisamente, perché una funzione puntatore che restituisce un puntatore ad un array allocatable clobber il primo elemento di tale matrice per il chiamante? Più precisamente ancora, perché non indicando un puntatore (b
) produrre un effetto collaterale di un altro puntatore (a
), in cui gli obiettivi provengono da diverse funzioni che si scrivono in modo da non interagire tra loro a tutti?
Avvertimenti
ottengo questo comportamento usando il compilatore GNU Fortran v.4.3.3, l'esecuzione di un laptop Intel con Ubuntu (Jaunty). I risultati possono variare, che potrebbe essere ancora più interessante. Infine, come sempre potrebbe essere un errore dell'operatore da parte mia, che sarebbe interessante per me, almeno.
Codice
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
Soluzione
Variabile array di function1 è una variabile locale - perché è stata dichiarata senza l'attributo "salvare", non è persistente e non è definito quando la funzione termina. Si assegna l'indirizzo di array per function1, "mantenere" questo indirizzo, ma l'indirizzo non è significativa una volta la variabile diventa indefinito dopo l'uscita dalla funzione. Un probabile implementazione è che array di function1 sarà posto sullo stack, e quella zona dello stack saranno liberati per altri usi al ritorno FUNCTION1. Ma questa è solo una supposizione ad un probabile implementazione - il punto chiave è che non ti è permesso di utilizzare il valore del puntatore dopo la variabile diventa indefinito. variabili allocatable vengono deallocate automaticamente quando escono di portata meno che non li dichiara con l'attributo "save".