2013-05-08 12 views
6

Obecnie próbuję zakodować mały podprogram w Fortranie, aby zwolnić wszystkie przydzielone zmienne w pamięci, gdy mój program dojdzie do błędu, tj. Nie udało się załadować pliku lub nieistniejący potrzebny plik. W tym momencie wykonanie musi zostać zakończone, ale nie wszystkie alokatory są przydzielane w sposób konieczny (zależy to od tego, gdzie na kodzie pojawił się błąd), więc nie mogę wykonać czyszczenia, usuwając wszystkie z nich.Fortran DEALLOCATE

Moje obecne podejście jest następujące:

SUBROUTINE Cleanup(A) 

    REAL(8), ALLOCATABLE, DIMENSION(:) :: A 

    IF (ALLOCATED(A)) THEN 
     DEALLOCATE(A) 
    END IF 

END SUBROUTINE 

i nazywają "Oczyszczanie" dla każdego allocatable. Problem polega na tym, że nie wszystkie moje zmienne są wymiarami 1. W niektórych z nich mam do trzech wymiarów.

Najpierw pomyślałem o napisaniu 3 różnych podprogramów dla różnych wymiarów i przy użyciu przeciążenia, ale to nie wydaje się być bardzo eleganckie.

Wtedy przyszło mi do głowy, że może mógłbym przekazać wskaźnik zamiast argumentu A, ale mam google'a i wygląda na to, że nie można zwolnić zmiennej docelowej za pomocą wskaźnika.

Wszelkie pomysły na temat tego, jak to zrobić prawidłowo?

Dzięki.

+4

Po zakończeniu wykonywania wszystkie zasoby wykorzystywane przez Twój kod są automatycznie zwalniane w dowolny sposób, więc nie musisz się martwić o jednoznaczne zwolnienie ich. –

+1

Wiem, że Fortran automatycznie zwalnia pamięć, ale w tym przypadku piszę bibliotekę dll, która jest wywoływana z Labview, więc to właśnie zarządza pamięcią. Gdy biblioteka DLL dojdzie do błędu, Labview nagle zatrzymuje się, a jeśli spróbuję ponownie wykonać, wyświetli komunikat "Array is already allocation" i zostanie wyłączony. Oznacza to, że pamięć nie jest prawidłowo przydzielana. – derkomai

+1

Uwaga: "rzeczywisty (8)" nie ma 8 bajtów. Przenośny sposób to 'use ISO_FORTRAN_ENV',' real (real64) 'dla 64 bitów. –

Odpowiedz

7

Moje podejście do tego by użyć kombinacji następujących czynności:

  • Od Fortran 95, wszystkich lokalnych un zapisane zmiennych allocatable które zostały przydzielone, gdy kończy procedury są automatycznie zwalniane. To, czy ma to zastosowanie, zależy od tego, w jaki sposób wywoływana jest biblioteka DLL, a co za tym idzie, czy w rzeczywistości można tak zorganizować elementy, aby wszystkie alokowane zasoby były niezapisanymi lokalami.

  • Od Fortran 2003 (lub Fortran 95 + przydzielający TR - ten poziom języka jest szeroko obsługiwany wśród utrzymywanych kompilatorów Fortran) przydziałowe faktyczne argumenty przekazane do przypisanych argumentów typu INTENT (OUT) zostaną automatycznie zwolnione przed rozpoczęciem procedury . Twoja procedura czyszczenia w pytaniu wymaga jedynie dodania deklaracji atrapa jako INTENT (OUT), a następnie nie ma potrzeby wykonywania testu IF lub DEALLOCATE. Nadal musisz napisać procedurę dla każdego typu i rangi, które musisz oczyścić.

  • Podobnie do poprzednich, alokowane składniki zmiennych typu pochodnego przekazane do atrapa typu INTENT (OUT) zostaną automatycznie zwolnione. Więc możesz być w stanie zebrać wszystkie swoje alokowane zmienne razem jako komponenty w obiekcie typu pochodnego. Wyczyszczenie polega wówczas na przejściu tego obiektu do procedury z manekinem INTENT (OUT). INTENT (OUT) tutaj również resetuje komponenty, które mają domyślną inicjalizację z powrotem do ich "domyślnej" wartości. Być może jest jeszcze inne sprzątanie, które musisz ręcznie zrobić w tym momencie (zamknij pliki itp.).

  • Alternatywnym podejściem, używając ponownie typów pochodnych ze wszystkimi zmiennymi jako komponentami, jest umożliwienie alokacji obiektu typu wyprowadzonego. Kiedy chcesz oczyścić, po prostu zwolnij ten jeden obiekt - jego składniki zostaną automatycznie zwolnione. Fortran 2003 pozwala na uruchomienie ostatecznej procedury z tego rodzaju zdarzenia, jeśli w tym momencie będziesz musiał wykonać dodatkowe czynności porządkowe.

typ pochodny podejście ułatwia również mieć wiele wystąpień niezależnie DLL obsługuje niezależnie aktywne w tym samym czasie (wystarczy kilka obiektów typu pochodnego).

Przykłady pochodnej podejścia typu, Dane:

TYPE MyType 
    REAL, ALLOCATABLE :: variable_one(:) 
    INTEGER, ALLOCATABLE :: variable_two(:) 
    ... 
END TYPE MyType 

CEL (Out) obojętne

TYPE(MyType) :: object 
ALLOCATE(object%variable_one(xxx)) 
ALLOCATE(object%variable_two(yyy)) 
... 
IF (things_have_gone_wrong) CALL Cleanup(object) 
... 
SUBROUTINE Cleanup(arg) 
    TYPE(MyType), INTENT(OUT) :: arg 
END SUBROUTINE Cleanup 

ALLOCATABLE obiektu.

TYPE(MyType), ALLOCATABLE :: object 
ALLOCATE(object) 
ALLOCATE(object%variable_one(...)) 
ALLOCATE(object%variable_two(...)) 

... 
IF (things_have_gone_wrong) DEALLOCATE(object) 
+1

To działa świetnie, dziękuję bardzo! – derkomai

+2

Innym sposobem ja znalazłem rozwiązania tego problemu jest użycie makra preprocesora: #define Cleanup (A) JEŻELI (nadany (A)) zwalnianie (A) Wywołany, Cleanup spełnia swoje zadanie. – derkomai

Powiązane problemy