Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations strongm on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

recursive subroutines and allocatable arrays 3

Status
Not open for further replies.

billgray1234

Programmer
Mar 14, 2011
39
i'm using fortran 90/95.
i'm using recursive subroutines.
i need to use arrays within these subroutines. i'm trying to determine whether i can use allocatable arrays, or whether i instead have to use "fixed size" arrays.

as you probably know, when using allocatable arrays, if they have already been allocated (i.e. they are currently in use), then they have to be deallocated first, if they are to be allocated again (i.e. used again).
does this also hold true if :-

1) the allocatable array is used in a recursive subroutine, and
2) the allocatable array is not a part of the subroutine dummy arguement list, and

AFTER the array has been allocated, but BEFORE the array has been deallocated, either :-

3) the recursive subroutine calls itself, or
4) control is "returned" to the calling program (using the word RETURN) ?

for example, is the code below valid, or does the array A have to instead be declared as a "fixed size" array (i.e. have a fixed dimension) ? my guess is that A has to instead be declared as a "fixed size" array.


RECURSIVE SUBROUTINE F ( X1 , X2 )

INTEGER, INTENT (INOUT) :: X1
INTEGER, INTENT (INOUT) :: X2


INTEGER :: IA
REAL, ALLOCATABLE, DIMENSION :)) :: A


IA = 3, say
ALLOCATE ( A (IA) )


IF ( X1 < 5 ) THEN
...X1 = X1 + 1
...CALL F ( X1 , X2 )
ELSE
...perform some "final" calculation with X2, and A
...RETURN
END IF


DEALLOCATE ( A )

END SUBROUTINE F
 
I don't have practice with recursion, but I don't see anything wrong with your code.

Your point 4, though is not true...return does not return to the "calling" program, it simply returns to the previous level subroutine F that called this level one....there is another return that you do not show, it is right before "END SUBROUTINE F" ...this is the one that will return this call to the previous level, too, after you are done with the IF-THEN clause and so you will have a chance to de-allocate the array allocated at that level.

Anyway, that's what I see.
 
Question is, if an recursive procedure gets a new set of local variables allocated or not. From the examples in my textbook I would assume that this is the case. So each allocation of a in the recursive procedure would allocate new memory for a new variable a. Then your code seems okay.

But you can pretty fast run out of memory depending on the size of your matrix and the number of recursions. So you should include some errorhandling to have a graceful exit if this occurs:

Code:
allocate (a (ia), status = iError)
if (iError .ne. 0) then
    write (*,*) 'running out of memory'
    return     ! include iError into argument list of F to have a flag that the calling routine could act on.
endif

In addition you should make sure that you do not produce a memory leak, that is, that all instances of a get deallocated. As far as I understand your code a does not get deallocated if your program returns in the else-if clause. And this seems to be the main exit for the routine, that is all instances return from there when executed successfully. So you may end with a piece of memory unusable equal to the size of a multiplied by the number of recursions. So you should deallocate prior to any return.

Norbert


The optimist believes we live in the best of all possible worlds - the pessimist fears this might be true.
 
thanks for your replies.

in reply to your replies :-

Salgerman :- you are correct (as usual!), about the term "calling program". i wrote "calling program", but i meant "calling CODE" -- which refers to the code that called the subroutine. Correct me if i'm wrong, but "calling CODE" refers to either a subroutine / function / main program, depending on which one did the "calling".

gummibaer :- you are also correct (as usual!), about the "incorrect" deallocation of A (due to the IF--ELSE IF--END IF clause) in the code i supplied. instead, the code i supplied SHOULD have looked like this :-


RECURSIVE SUBROUTINE F ( X1 , X2 )

INTEGER, INTENT (INOUT) :: X1
INTEGER, INTENT (INOUT) :: X2


INTEGER :: IA
REAL, ALLOCATABLE, DIMENSION :)) :: A


IA = 3, say
ALLOCATE ( A (IA) )


IF ( X1 < 5 ) THEN
...X1 = X1 + 1
...CALL F ( X1 , X2 )
ELSE
...perform some "final" calculation with X2, and A
...DEALLOCATE ( A )
...RETURN
END IF


DEALLOCATE ( A )


END SUBROUTINE F



finally, to both Salgerman and gummibaer :- i think you are both correct, about the above code being "ok" (i.e. "valid"). each time the recursive subroutine calls itself, we are effectively looking at a fresh "instance" of that subroutine. in each "instance", a new vector A is allocated, but the vector is "local" to that subroutine (i.e. as opposed to being a "global" variable, that can be globally accessed by any subroutine / function / main program). so, based on all of the theory i've read on this topic, i'm thinking the above code IS "ok".
 
calling procedure" instead of "calling code" is the right expression, a procedure being a subroutine, function, main program... which has been compiled.

You do not need to deallocate your allocatable array A. This is done automatically when returning to the calling procedure.

François Jacq
 
sorry that this reply is so late.

you said that allocatable arrays (that have been ALLOCATEd in the current "procedure") are automatically deallocated (upon return to the "calling procedure").
does the same apply with files ? i.e. are all files (that have been OPENed during the current "procedure") automatically CLOSEd (upon return to the "calling procedure") ?


also, i just wanted to check something, based on what you said :-

again, you said that allocatable arrays (that have been ALLOCATEd during the current "procedure") are automatically deallocated (upon return to the "calling procedure").
does that mean to say that it's actually NOT good programming practice to "manually" DEALLOCATE arrays, before returning to the "calling procedure" ? because, if i "manually" DEALLOCATE SOME of them (but not ALL of them), then the "procedure" will look incomplete (but will still compile, and run correctly).

ditto with files. if all files (that have been OPENed during the current "procedure") are automatically CLOSEd, then is it NOT good programming practice to "manually" CLOSE all such files ?
 
Files:

Files stay open as long as your program is running unless you close them by a CLOSE statement or you open another file under the same unit number. When your program terminates, then the system closes and saves the files unless declared otherwise in the OPEN, which is a non-standard option in some compilers (e.g. Compaq allows DISPOSE = 'DELETE' option to be specified in the open statement)

Allocatable arrays:

I think it a matter of personal preference if you rely on the automatic options, that your compiler provides - not only in the deallocation of arrays. I for myself hate all (!) automatic functions. Everywhere. I want to be in control of things, anytime. I even want to have my PC print what I type. If I type garbage, then my PC should print garbage and not autocorrect or autoformat it to something different, thazt I do not recognise. So for me manual deallocation of arrays is good programming practice, as I know for sure at what time the array becomes unavailable. I usually apply the save attribute to my allocatables to stop the system from deallocating of the arrays automatically (which is very important in window callback functions!). This way I get a runtime error (to be checked by the status clause in the allocate statement) when the system tries to allocate an array that allready is allocated. Then I know something in the flow of my prog went wrong, not just the allocation, that a procedure was called when it should not be called. This is essential for me as I do Window-applications where the program flow depends deeply on the user's actions.

That's just me, other may have different views with their good reasons for it.

Norbert


The optimist believes we live in the best of all possible worlds - the pessimist fears this might be true.
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top