Fortran Zeiger Funktionen: warum ist das Verhalten dieser Code ist in der Größenordnung von Funktionsaufrufen ab?

StackOverflow https://stackoverflow.com/questions/1580426

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.

  1. Wenn ich Punkt a auf das Ergebnis der function1, sind die Ergebnisse nicht korrekt. Das erste Element des a zu sein scheint "verprügelt". a hat 0, 2, 3
  2. Wenn ich Punkt b auf das Ergebnis der function2, sind die Ergebnisse korrekt sind. b bekommt 1, 2, 3.
  3. Noch merkwürdiger ist, zeigt b auf das Ergebnis der function2 nach zeigt a zu function1 ändert a, so dass es wird richtig. a dann hat 1, 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
War es hilfreich?

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.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top