2011-01-10 7 views
1

Ich frage mich, wie man ein Array von einer Funktion ohne Kenntnis der Form bis zur Laufzeit (einschließlich der angenommenen Form Arrays) zurückgibt. Ich werde es mit Beispielen erklären. Dies funktioniertFunktion Array zurückgeben ohne definierte explizite Form

module foo 
contains 
    function getArray(:) 
     real :: getArray(3) 
     integer :: i 
     do i=1,3 
     getArray(i) = 10.0*i 
     enddo 
    end function 

end module 

program xx 
    use foo 
    real :: array(3) 
    integer :: i 

    array = getArray() 
    print *, array 
end program 

Dies funktioniert auch, weil es den Einsatz von automatischen Arrays

module foo 
contains 
    function getArray(length) 
     integer :: length 
     real :: getArray(length) 
     integer :: i 
     do i=1,length 
     getArray(i) = 10.0*i 
     enddo 
    end function 

end module 

program xx 
    use foo 
    real :: array(5) 
    integer :: i 

    array = getArray(5) 
    print *, array 
end program 

Was ist mit diesem macht man? ist es Fortran gültig? habe ich ein Speicherleck in diesem Fall

module foo 
    contains 
    function getArray() 
     real, allocatable :: getArray(:) 
     integer :: length 
     integer :: i 

     length = 5 ! coming, for example, from disk 

     allocate(getArray(length)) 

     do i=1,length 
      getArray(i) = 10.0*i 
     enddo 

     ! cannot call deallocate() or a crash occurs 
    end function 

end module 

use foo 
    real :: array(5,5) ! get max size from other means, so to have enough space 
    integer :: i 

    array = getArray() 
    ! leaking memory here ? unexpected behavior ? 
end program 
+0

In Ihrem letzten Beispiel hat getArray zwei Dimensionen, aber Sie behandeln es als 1D-Array. Warum das? – canavanin

+0

@canavanin: Tippfehler –

Antwort

2

Wenn ich diesen Code zu kompilieren:

(Datei bar.f90)

program bar 

    use foo 

    real :: array(5,5) ! get max size from other means, so to have enough space 
    integer :: i 

    array = getArray() 
    ! leaking memory here ? unexpected behavior ? 

end program 

(Datei foo.f90)

module foo 
    contains 
    function getArray() 
     real, allocatable :: getArray(:,:) 
     integer :: length 
     integer :: i 

     length = 5 ! coming, for example, from disk 

     allocate(getArray(length,length)) 

     do i=1,length 
      getArray(i,:) = 10.0*i 
     enddo 

     ! cannot call deallocate() or a crash occurs 
    end function 

end module 

mit ifort -debug foo.f90 bar.f90

und lassen valgrind die ausführbare Datei überprüfen alles scheint in Ordnung:

valgrind --tool=memcheck --leak-check=yes --show-reachable=yes --num-callers=20 ./a.out 
==8019== Memcheck, a memory error detector 
==8019== Copyright (C) 2002-2009, and GNU GPL'd, by Julian Seward et al. 
==8019== Using Valgrind-3.6.0.SVN-Debian and LibVEX; rerun with -h for copyright info 
==8019== Command: ./a.out 
==8019== 
==8019== 
==8019== HEAP SUMMARY: 
==8019==  in use at exit: 0 bytes in 0 blocks 
==8019== total heap usage: 2 allocs, 2 frees, 108 bytes allocated 
==8019== 
==8019== All heap blocks were freed -- no leaks are possible 
==8019== 
==8019== For counts of detected and suppressed errors, rerun with: -v 
==8019== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 17 from 6) 

Wahrscheinlich bald jemand mit weit mehr Know-how wird antworten; Ich hoffe, das wird vorerst gehen.

3

Diese Fähigkeit einer Funktion, ein zuweisbares Array zurückzugeben, wird von TR 15581 bereitgestellt. Siehe http://www.nag.co.uk/nagware/np/doc/tr.asp. Die Funktion muss das Array zuweisen und "das Ergebnis einer zuweisbaren Array-Funktion wird automatisch freigegeben, nachdem es verwendet wurde", d. H. Kein Speicherleck!

Siehe auch die Diskussionen unter http://www.tek-tips.com/viewthread.cfm?qid=1613318&page=5 und http://software.intel.com/en-us/blogs/2008/03/31/doctor-it-hurts-when-i-do-this/.

Ein weiteres neues Feature von Fortran 2003 erlaubt es, wenn Sie es implementiert haben, "real :: array (5,5)" zu "array" auch als zuweisbar zu deklarieren, und es wird automatisch der richtigen Größe zugewiesen bei der Zuweisung - keine Vorabzuweisung. Sehr leicht! Dies ist in den späten Versionen von Intel Fortran verfügbar, ist aber standardmäßig nicht aktiv. Siehe den letzten Link oben.