DEALLOCATING DATA TYPE POINTERS

DEALLOCATING DATA TYPE POINTERS

Scott B.'s picture

Just a general coding question regarding data type pointer variables.

My question is for pointer data types that contain allocatable arrays such as the following example:

C DATA TYPE DECLARATION IN A MODULE
      TYPE TARRAY

	        INTEGER::POS

	        LOGICAL::USEVAL

	        DOUBLE PRECISION::VAL

	        DOUBLE PRECISION,DIMENSION(:),ALLOCATABLE::TIM,DAT

	      END TYPE 

	      !

	      TYPE TTYPE

	        INTEGER::NT

	        CHARACTER(20), DIMENSION(:),ALLOCATABLE::NAM

	        TYPE(TARRAY),DIMENSION(:),ALLOCATABLE::T

	      END TYPE

	      !

	      TYPE, EXTENDS (TTYPE):: TTYPEAUX

	        REAL,         DIMENSION(:),ALLOCATABLE:: FAC

	        INTEGER,      DIMENSION(:),ALLOCATABLE:: IDX 

	        LOGICAL                               :: PRNT

	      END TYPE
 

That are then declaired as a pointer as follows:

      TYPE(TTYPEAUX), POINTER:: DATA
      ALLOCATE(DATA)
 

After the pointer has been allocated the various allocatable parts in the data type are allocated. 

My question is will there be any memory leaks or problems if at the end of the code or when I no longer need the pointer I just use the following:

      DEALLOCATE(DATA)
 

Which would then DEALLOCATE the data type and all the allocatable arrays within it.

For that matter if DATA was only a regular pointer array would it deallocate the entire array or do I have to do something like:

      DATA=>NULL()
C or
      NULLIFY(DATA)
 

To remove it from memory or would those only disassociate the pointer leaving the array sitting in memory. (There maybe other features pointing to the pointer array.)

I personally hate pointers, but for this particle program that I am working on I have to use them.

 

Thanks for your help as always!

18 posts / 0 new
Last post
For more complete information about compiler optimizations, see our Optimization Notice.
Andrew Smith's picture

If you use a pointer allocation you will always need to explicitly deallocate to clear memory, unless you are terminating the program in which case the OS will clear the memory but it is probably better practice to code a deallocate.

The allocatable components should in theory be cleared automatically without coding.

Scott B.'s picture

Thanks Andrew, that is what I suspected, but wanted to make sure.

With the DEALLOCATE statement would also nullify all pointers that point to the original pointer. For example:

INTEGER,POINTER:: A,B
ALLOCATE(A)
B=>A
DEALLOCATE(A)

would also nullify B?

Steve Lionel (Intel)'s picture

No, it does not. The other pointers now have "undefined" status, which means you can't depend on their value.

Steve
Scott B.'s picture

That is fine, I just wanted to make sure that B would no longer hold the information or keep the the INTEGER stored in RAM.

Steve Lionel (Intel)'s picture

Once you deallocate A you don't know what B points to. Practically speaking, it will still point to the memory it did before, but that memory could have been reused. There is no way to detect whether or not it is still valid.

Steve
Scott B.'s picture

Ok cool, so say that B points to A, which is an array that uses 1GB or RAM.

When I deallocate A then the memory would be freed? (i.e. my ram usuage would go down 1GB.) 

or should I also have Nullify(B)

Steve Lionel (Intel)'s picture

The memory is released to the pool that can be allocated, but in nearly all cases, your RAM usage will not decrease.

Yes, an explicit nullify of B would be a good idea in this case.

Steve
Scott B.'s picture

Either

nullify(B)
C or
B=>NULL()

Could I so something like?

DEALLOCATE(A)
B=>A

Thanks so very much for your help with this, I am working on a huge gov modeling software and trying to improve/update it.

Steve Lionel (Intel)'s picture

You could do B=>A, but I strongly recommend against this as it is unclear to the reader what is going on. NULLIFY(B) is the preferred approach.

Steve
Scott B.'s picture

Sorry about the original incorrect psuedocode. I was trying to simplify about 10000 lines of code and how the pointers were handled between the various subroutines. They use a generic variable "B" and global storage variables "A" and "C" and they flip to have B point to A and C when it is uses.

-----------------------------------------------------------------------------------

OK thanks a ton, that is what I will do. Now that I recheck the code I realized its slightly different in how it allocates. The following is an example

       INTEGER,DIMENSION(:),POINTER:: A,C
       INTEGER,DIMENSION(:),POINTER:: B
      B=>A   !A is undef
       ALLOCATE (B(10000))
C DO SOME STUFF WITH B
       A=>B    !Software considers this saving A
      B=>C    !C is undefined
       ALLOCATE (B(10000))
C DO STUFF WITH B
C THEN 
       C=>B   !Software considers this saving C
C THEN WHEN STUFF FROM A IS NEDED
      B=>A
C DO STUFF WITH B
C THEN WHEN A AND C ARE NO LONGER NEEDED (AND NEITHER IS B)
       DEALLOCATE(A)
       DEALLOCATE(C)

 

That is a just a psuedocode for it, but it flips back and forth between multiple pointers. At the end of the code I should then also include

NULLIFY(B)

To be consistent.

 

Thank you so very much for all your help with this, its been really illuminating.

FortranFan's picture

Based on your pseudo-code example, I suggest:

  • Applying the TARGET attribute instead for POINTER for B
  • DEALLOCATE B, but use IF (ALLOCATED(B)) a safety check
  • Use IF (ASSOCIATED(..) before using A and C
  • NULLIFY A and C before procedure end (or program termination)
Andrew Smith's picture

Your pseudo code is dodgy since you loose track of the memory you allocate to B. The line B => C points to a unassociated pointer (or rather one with undefined state).  Then you point A at B and you have lost all pointers to the memory.

I don't see why you cannot use a base variable with allocatable and target attributes to hold the data. You can have all the pointers you want to point at it and there is never a danger of memory leaking whatever you do with the pointers.

Scott B.'s picture

Hi Andrew, sorry I did make a few mistakes in the psuedocode and fixed it so its not so ambiguous. See the post above.
 

The way to view it is that the pointer variables A and C hold the data and B is a variable used within the subroutines. I think this was introduced into the code as a method of expanding the utility of the original code (A and C are in the code are actually an index of a global data type that represent different features). The psuedocode that I fixed above is the general structure of the code if it was indexed to have two terms (e.g. A and C)

Thanks

Scott B.'s picture

Has anyone had a chance to look at that revised code?

IanH's picture

The revised code looks ok, but there are pointless statements in it - lines 03 and 07, where you change the pointer association status of B to be undefined, and then immediately re-associate it with an object that you allocate.

In the absence of some other reason that is yet to be stated, I absolutely wouldn't deliberately design things this way.  Andrew's suggestion is reasonable.  There's also the option of simply making B a procedure argument (if it isn't already) in the bits titled "do things with B" - when you want to work on A, pass in A, when you want to work on C, pass in C.  Is there a real reason to have B floating around in the same scope as A and C?

Scott B.'s picture

The program is unfortunately enormous and was later modified to be able to run with multiple copies of itself within it by the above pointer scheme.

 

At the beginning of each subroutine there was an added call to a "point" subroutine that establishes all the pointers (B pointing to the active data set, say A) then at the end of each subroutine it saves the pointers by calling a "save" subroutine that re-points A to B. Then the next time the subroutine was called the beginning would have B point to C and then at the end save it by having C point to B. 

 

This was done (long before my time) because there were literally 1000's of variables that change across a few hundred subroutines and made it so only two lines had to be added for each subroutine. Ultimately if there ever is funding I love to rewrite it to not follow this structure.

 

Thanks for all your advice.

FortranFan's picture

Quote:

Scott B. wrote:

The program is unfortunately enormous and was later modified to be able to run with multiple copies of itself within it by the above pointer scheme.

At the beginning of each subroutine there was an added call to a "point" subroutine that establishes all the pointers (B pointing to the active data set, say A) then at the end of each subroutine it saves the pointers by calling a "save" subroutine that re-points A to B. Then the next time the subroutine was called the beginning would have B point to C and then at the end save it by having C point to B.

This was done (long before my time) because there were literally 1000's of variables that change across a few hundred subroutines and made it so only two lines had to be added for each subroutine. Ultimately if there ever is funding I love to rewrite it to not follow this structure.

Scott B.,

To be frank, I've no comprehension whatsover of what you are trying to convey by your pseudo-code or by your explanations.  Statements such as "The program.. was later modified to be able to run with multiple copies of itself within it by the above pointer scheme" and ".. then at the end of each subroutine it saves the pointers by calling a "save" subroutine that re-points A to B.. " are completely beyond my abilities to understand what could be going on.

"I love to rewrite it to not follow this structure" - perhaps it will help you if you can start off by writing a simple, working program that operates on a small set of data in about the same fashion as your existing code and you test and validate it thoroughly - this is as opposed to postulating some pseudo-code that is not constrained by any logic/algorithmic requirements and which is difficult to understand.  This approach may even help you understand better how your current code works while giving you ideas on how to restructure it when you get the funding to do so.

Login to leave a comment.