- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I have a program with a derived type that has a final procedure and an assignment operator overload, as shown below:
module MyTypeModule implicit none type MyType real, allocatable, dimension(:) :: myArray contains final :: Finalize end type MyType interface assignment(=) module procedure :: MyTypeAssign end interface contains subroutine Finalize(this) type(MyType), intent(inout) :: this if (allocated(this%myArray)) deallocate(this%myArray) end subroutine Finalize subroutine MyTypeAssign(left,right) type(MyType), intent(out) :: left type(MyType), intent(in) :: right if (allocated(right%myArray)) left%myArray = right%myArray end subroutine MyTypeAssign end module MyTypeModule program TestCodeAssignmentFinalize use MyTypeModule implicit none type(MyType) :: a,b allocate(a%myArray(10)) a%myArray = 1.0 write(*,*) "a is allocated? ",allocated(a%myArray) write(*,*) "setting a = a" a = a write(*,*) "a is allocated? ",allocated(a%myArray) write(*,*) "b is allocated? ",allocated(b%myArray) write(*,*) "setting b = a" b = a write(*,*) "b is allocated? ",allocated(b%myArray) end program TestCodeAssignmentFinalize
The console output is as follows:
a is allocated? T setting a = a a is allocated? T b is allocated? F setting b = a b is allocated? T
When I comment out the assignment interface, I get the following console output:
a is allocated? T setting a = a a is allocated? F b is allocated? F setting b = a b is allocated? F
You can see that with intrinsic assignment, the array in a is getting deallocated before being assigned to itself, whereas it remains allocated with the overloaded assignment. Is this expected behavior? If it is expected, then is there a way to get around the deallocation when I have a = a and intrinsic assignment?
Link Copied
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
The deallocation is happening in your final routine - I assume you know that but the wording of your question makes me wonder.
I think your real question is: "Is it correct that intrinsic assignment triggers finalization but defined assignment doesn't?" The answer is yes. Quoting the standard:
9 When an intrinsic assignment statement is executed, the variable is finalized after evaluation of expr and before the definition of the variable.
NOTE 4.49
If finalization is used for storage management, it often needs to be combined with defined assignment.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I can't check current release, but the results in the original post indicate that the compiler isn't honouring the ordering specified by that standard fragment, when the defined assignment interface block is commented out and intrinsic assignment is in use. The value that results from evaluating the right hand side of the assignment has an allocated component, so the value of the left hand side after the assignment should similarly have an allocated component.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Thank you for your replies. Yes, I understand that the deallocation is happening in my final routine. I am using Intel Visual Fortran Compiler 17.0.2.187 [IA-32].
We are running into the situation where where have something like array(a)=array(b) and a=b, and array's type has an allocatable component. The final routine deallocates this component, and we don't have the assignment overloaded. The result is the array element is being finalized before the assignment occurs, and thus it ends up with a deallocated array. If this is by design, then we will work with it, but I don't want to work around this issue if future compiler releases will handle it differently.
It seems like the correct way to handle this is to implement overloaded assignments along with final routines.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
gfotran 6.3 produces results supporting IanH's interpretation so it appears ifort is perhaps not handling the intrinsic case properly. I opened an internal defect report w/Development on this for them to analyze further.
(Internal tracking id: CMPLRS-42883)
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
If I change the interface assignment operator to be a type-bound assignment operator, I obtain the same results as the intrinsic assignment operation above:
module MyTypeModule implicit none type MyType real, allocatable, dimension(:) :: myArray contains final :: Finalize generic :: assignment(=) => GenericAssign procedure :: GenericAssign => MyTypeAssign end type MyType contains subroutine Finalize(this) type(MyType), intent(inout) :: this if (allocated(this%myArray)) deallocate(this%myArray) end subroutine Finalize subroutine MyTypeAssign(left,right) class(MyType), intent(out) :: left type(MyType), intent(in) :: right write(*,*) "Perform assignment" if (allocated(right%myArray)) left%myArray = right%myArray end subroutine MyTypeAssign end module MyTypeModule program TestCodeAssignmentFinalize use MyTypeModule implicit none type(MyType) :: a,b allocate(a%myArray(10)) a%myArray = 1.0 write(*,*) "a is allocated? ",allocated(a%myArray) write(*,*) "setting a = a" a = a write(*,*) "a is allocated? ",allocated(a%myArray) write(*,*) "b is allocated? ",allocated(b%myArray) write(*,*) "setting b = a" b = a write(*,*) "b is allocated? ",allocated(b%myArray) end program TestCodeAssignmentFinalize
And the output is:
a is allocated? T setting a = a Perform assignment a is allocated? F b is allocated? F setting b = a Perform assignment b is allocated? F
This output is different from the interface assignment results, which is unexpected.

- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page