Fortran DEALLOCATE

I am currently trying to encode a small routine in Fortran to free all allocated variables in memory when my program arrives at an error, that is, it was not possible to load a file or a nonexistent file. At this stage, the execution should be completed, but not all distributed attributes are necessarily distributed (it depends on where the error appeared in the code), so I can not do the cleaning, freeing all of them.

My current approach is this:

SUBROUTINE Cleanup(A) REAL(8), ALLOCATABLE, DIMENSION(:) :: A IF (ALLOCATED(A)) THEN DEALLOCATE(A) END IF END SUBROUTINE 

and call "Cleanup" for each highlighted. The problem is that not all of my variables are dimension-1. Some of them have up to three dimensions.

At first I thought about writing 3 different routines for different dimensions and using overload, but that doesn't seem very elegant.

Then it occurred to me that maybe I can pass a pointer instead of the actall argument, but I have googled, and it looks like you cannot release the target variable through the pointer.

Any ideas on how to do this correctly?

Thanks.

+6
source share
1 answer

My approach to this will use the following combination:

  • As with Fortran 95, all local unsaved distributed variables that are allocated at the end of the procedure are automatically freed. Whether this is applicable depends on how your DLL is called, and on whether you can actually structure such things so that all your allocatables are unsaved locales.

  • As of Fortran 2003 (or Fortran 95 + allocatable TR - this level of language is widely supported among supported Fortran compilers). The distributed actual arguments passed to the argument arguments assigned by INTENT (OUT) will be automatically released before the execution starts. Your cleanup procedure in this question just needs to add a dummy argument declaration as INTENT (OUT), and then there is no need to test IF or DEALLOCATE. You still need to write a procedure for each type and rank that you need to clear.

  • Like the previous ones, the allocated components of variables of a derived type passed to the dummy argument INTENT (OUT) will be automatically freed. This way you can collect all of your distributed variables together as components in an object of a derived type. Then, cleaning simply involves passing this object to the procedure using the INTENT (OUT) dummy. INTENT (OUT) here also resets components for which the default initialization returns to their default value. Perhaps there is another cleaning that you need to do manually at this point (close files, etc.).

  • An alternative approach, again using derived types with all your variables as components, is to make the object of the derived type self-distributing. When you need to clean, just free this object - its components will be automatically freed. Fortran 2003 allows you to run the final procedure from this kind of event, if at this point you need to perform an additional cleanup.

The derived type approach also makes it easy to have multiple instances, regardless of whether your DLL is independently active at one time (you only have a few objects of the derived type).

Examples of a derived type approach given:

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

Dummy INTENT (OUT)

 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 

The object is ALLOCATABLE.

 TYPE(MyType), ALLOCATABLE :: object ALLOCATE(object) ALLOCATE(object%variable_one(...)) ALLOCATE(object%variable_two(...)) ... IF (things_have_gone_wrong) DEALLOCATE(object) 
+7
source

Source: https://habr.com/ru/post/944501/


All Articles