Fortran Zeiger Funktionen: warum ist das Verhalten dieser Code ist in der Größenordnung von Funktionsaufrufen ab?
Frage
Kontext
Das Spielzeug Fortran-Code geschrieben unten Anrufe zwei Zeigerfunktionen. Das heißt, das Rück beide Funktionen einen Zeiger. In der Tat sind sie beide Array Zeiger. Beide versuchen, dasselbe zu tun, die einen Ganzzahl-Array Zeiger referenzieren ein Integer-Array zurückzubringen ist, die drei Elemente 1, 2 und 3. Die erste Funktion verwendet den Zeigerzuweisungsoperator (=>), um die Funktionszeiger zeigen auf ein zuweisbaren Array, das die Daten enthält. Die zweite Funktion ordnet einen Block von dynamischen Speicher direkt über den Zeiger, um die Daten zu speichern. Das rufende Programm nur druckt die Elemente des zurückgegebenen Arrays (s).
Hier ist, was ich seltsam finden.
- Wenn ich Punkt
a
auf das Ergebnis derfunction1
, sind die Ergebnisse nicht korrekt. Das erste Element desa
zu sein scheint "verprügelt".a
hat0
,2
,3
- Wenn ich Punkt
b
auf das Ergebnis derfunction2
, sind die Ergebnisse korrekt sind.b
bekommt1
,2
,3
. - Noch merkwürdiger ist, zeigt
b
auf das Ergebnis derfunction2
nach zeigta
zufunction1
änderta
, so dass es wird richtig.a
dann hat1
,2
,3
.
Frage
Warum tritt das? Genauer gesagt hat, warum eine Zeigerfunktion, die clobber das erste Element des Arrays für den Anrufer einen Zeiger auf ein zuweisbaren Array zurückgibt? Genauer noch, warum einen Zeiger (b
) erzeugt auf einem anderen Zeiger (a
) eine Nebenwirkung nicht zeigen, wo die Ziele aus verschiedenen Funktionen kommen, die, um nicht miteinander interagieren überhaupt geschrieben?
Caveats
ich dieses Verhalten erhalten die GNU-Fortran-Compiler v.4.3.3 verwenden, einen Intel-Laptop mit Ubuntu (Jaunty) ausgeführt wird. Ihre Ergebnisse können variieren, was noch interessanter sein könnte. Schließlich, wie immer es könnte Bedienungsfehler meinerseits sein, die zumindest für mich interessant wäre.
Code
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
Lösung
Variable array von function1 ist eine lokale Variable - weil es ohne die „save“ Attribut deklariert wird, ist es nicht dauerhaft ist und nicht definiert ist, wenn die Funktion beendet. Sie ordnen die Adresse array zu function1 „hält“ diese Adresse, aber die Adresse ist nicht sinnvoll, wenn die Variable nach dem Verlassen der Funktion nicht definiert wird. Eine wahrscheinliche Implementierung ist, dass array von function1 wird auf den Stapel gelegt werden, und dieser Bereich des Stapels wird für andere Zwecke als function1 kehrt befreit werden. Aber das ist nur eine Vermutung an einer wahrscheinlich Implementierung - der entscheidende Punkt ist, dass es nicht erlaubt ist den Zeigerwert zu verwenden, nachdem die Variable nicht definiert wird. Zuordnungsbare Variablen werden automatisch freigegeben, wenn sie von Umfang hinausgehen, wenn man sich mit dem „save“ Attribut deklariert.