2012-10-24 6 views
11

Następujący kod zwraca błąd segmentacji, ponieważ przydzielana tablica, którą próbuję przekazać, nie jest poprawnie rozpoznawana (rozmiar zwraca 1, kiedy powinien być 3). Na tej stronie (http://www.eng-tips.com/viewthread.cfm?qid=170599) podobny przykład wydaje się wskazywać, że powinien działać poprawnie w F95; mój plik kodu ma rozszerzenie .F90, ale próbowałem go zmienić na F95 i używam gfortran do kompilacji.Jak przekazywać alokowane tablice do podprogramów w Fortranie

Zgaduję, że problem powinien polegać na tym, że przekazuję tablicę alokacji do podprogramu; Co ja robię źle?

!%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%! 
PROGRAM test 
!%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%! 
IMPLICIT NONE 
DOUBLE PRECISION,ALLOCATABLE :: Array(:,:) 
INTEGER      :: iii,jjj 

ALLOCATE(Array(3,3)) 
DO iii=1,3 
DO jjj=1,3 
    Array(iii,jjj)=iii+jjj 
    PRINT*,Array(iii,jjj) 
ENDDO 
ENDDO 
CALL Subtest(Array) 

END PROGRAM 
!%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%! 
SUBROUTINE Subtest(Array) 
DOUBLE PRECISION,ALLOCATABLE,INTENT(IN) :: Array(:,:) 
INTEGER         :: iii,jjj 

PRINT*,SIZE(Array,1),SIZE(Array,2) 
DO iii=1,SIZE(Array,1) 
DO jjj=1,SIZE(Array,2) 
    PRINT*,Array(iii,jjj) 
ENDDO 
ENDDO 

END SUBROUTINE 
!%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%! 
+0

Należy zauważyć, że alokowane atrapowe argumenty są w rzeczywistości (szeroko wspierane - w tym gfortran od kilku lat) funkcją Fortran 2003. – IanH

Odpowiedz

28

Jeśli dana procedura ma fałszywy argument, który można alokować, wymagany jest jawny interfejs w dowolnym zasięgu wywoływania.

(Istnieje wiele rzeczy, które wymagają wyraźnego interfejs, allocatable manekin jest tylko jeden).

Można przewidywać, że wyraźny sprzęgowi się poprzez umieszczenie bloku interfejsu dla podprogramu wewnątrz głównego programu. Alternatywą i daleko, o wiele lepszym rozwiązaniem jest umieszczenie podprogramu wewnątrz modułu, a następnie użycie tego modułu w programie głównym - automatycznie tworzony jest jawny interfejs. Jest taki przykład na stronie Eng-tips, do której podałeś link - patrz post przez xwb.

Zauważ, że to ma sens tylko do manekina argumentu mieć allocatable atrybut Jeśli zamierzasz robić coś związanego z jego statusu alokacji - sprawdzanie stanu, przesunięciu go, zwalnianie go itp

+0

Dzięki, to był mój problem. Wiedziałem, że niektóre funkcje (nie pamiętam nazwy, które mieli, ale myślę, że to one zmieniły parametry wejściowe) wymagały jawnych interfejsów, ale nie wiedziałem, że alokacja była taka sama. I tak, kod został stworzony w celu debugowania mojego prawdziwego kodu. – Nordico

5

Proszę również zwróć uwagę, że Twój przydzielający atrapowy argument array jest zadeklarowany jako intent(in), co oznacza, że ​​jego status przydziału będzie zgodny z faktycznym argumentem (i nie może zostać zmieniony podczas procedury). Faktyczny argument przekazany do twojego podprogramu może być nieprzydzielony, a zatem niedozwolony do odniesienia, nawet z jawnym interfejsem. Kompilator nie będzie o tym wiedział, a zachowanie zapytań takich jak size jest w takich przypadkach niezdefiniowane.

W związku z tym należy najpierw sprawdzić stan alokacji array za pomocą allocated(array) przed odniesieniem do jego zawartości. Chciałbym dalej proponuję wdrożyć pętle na całej tablicy z lbound i ubound, ponieważ w ogóle nie mogą być pewni o granicach array Add

subroutine subtest(array) 
    double precision, allocatable, intent(in) :: array(:,:) 
    integer         :: iii, jjj 

    if(allocated(array)) then 
    print*, size(array, 1), size(array, 2) 
    do iii = lbound(array, 1), ubound(array, 1) 
     do jjj = lbound(array, 2), ubound(array, 2) 
     print*, array(iii,jjj) 
     enddo 
    enddo 
    endif 
end subroutine 
+0

Uwaga: Dodano to jako nową odpowiedź, ponieważ nie mogę jeszcze komentować innych osób. Jest to raczej rozszerzenie odpowiedzi IanH, która moim zdaniem jest ważna, ponieważ ta subtelność jest również pomijana w poście xwb na eng-tips.com. Nie chciałem wejść z dużą zmianą; nie wahaj się połączyć tego w jedną odpowiedź. – sigma

+0

ubound wydaje się mieć taki sam efekt jak Rozmiar; jaka jest różnica? A użycie lbound jest na wypadek, gdyby tablica zaczynała się od indeksu wyższego niż 1? Czy to się może stać? – Nordico

+3

'size' daje całkowitą liczbę elementów tablicy (bez ciemnego argumentu) lub liczbę wzdłuż dowolnego wymiaru (z ciemnym argumentem).Możesz przydzielić tablicę z granicami '(-2: 0, -2: 0)', a rozmiar będzie nadal wynosił 3 wzdłuż każdego wymiaru, ale 'tablica (1: 3, 1: 3)' jest niezdefiniowana. Jest to przeciwieństwo nierozpoznawalnej matrycy fikcyjnej z założonym kształtem, gdzie dolna granica jest rzeczywiście przyjęta jako 1, jeśli nie została określona. – sigma

1

Jest to prosty przykład, który używa allocatable manekina z argumentów moduł.

Powiązane problemy