Intel® Fortran Compiler
Build applications that can scale for the future with optimized code designed for Intel® Xeon® and compatible processors.

Finalization of an object produced by a factory.

Ilie__Daniel
Beginner
580 Views

Dear All,

The attached project implements a Factory for two products.

The program expects an integer argument. If the argument is positive, the program creates Product 1, otherwise Product 2.

Before the program ends the Factory cleaning code is called. This deallocates the polymorphic pointer (to either Product 1 or Product 2).

My question is: Why is neither the finalizer for Product 1 nor Product 2 called?

For example, if I run the program with argument 20 I would expect to get in the console:

  • Factory: Creating Product 1.
  • Factory: Creation success.
  • Product 1: Using.
  • Product 1: Destroying.
  • Factory: Destroying product success.

Instead the line in bold (Product 1: Destroying) is missing.

Am I doing something wrong?

Thank you for any suggestions.

0 Kudos
8 Replies
jimdempseyatthecove
Honored Contributor III
580 Views

Pointers do not automatically deallocate when the pointer goes out of scope. Try this:

program Factory
...
type(Product1_t), allocatable :: prod1
type(Product2_t), allocatable :: prod2
type(Polymorphic_t), pointer :: prodX
...
if(arg1 .ge. 0) then
  allocate(prod1)
  prodX => prod1
else
  allocate(prod2)
  prodX => prod2
endif 

call usingProd(prodX)

The finalize should be called upon exit of PROGRAM
*** However, some versions did not perform the auto-deallocation from the PROGRAM procedure, therefor, you may need to encapsulate the above in a subroutine

program Factory
 call Encapsulate
end program

subroutine Encapsulate
...
type(Product1_t), allocatable :: prod1
type(Product2_t), allocatable :: prod2
type(Polymorphic_t), pointer :: prodX
...
if(arg1 .ge. 0) then
  allocate(prod1)
  prodX => prod1
else
  allocate(prod2)
  prodX => prod2
endif 

call usingProd(prodX)
end subroutine Encapsulate

Jim Dempsey

0 Kudos
Ilie__Daniel
Beginner
580 Views

Hi Jim,

I was hopping that the deallocation of the pointer would automatically result in the destruction of the object.

In your example, I can see that the two targets prod1 and prod2 would eventually go out of scope and get destroyed because they are unsaved.

 

0 Kudos
jimdempseyatthecove
Honored Contributor III
580 Views

>> I can see that the two targets prod1 and prod2 ...

Thanks for correcting my omission of target on the allocatables. Pointers in C++ do not call the dtor when it goes out of scope, Fortran is no different. It is the programmer's responsibility to manage the lifetime of these (pointer allocated) objects.

Also, it doesn't make sense to deallocate a pointee as compiler/runtime cannot ascertain if the pointee has no remaining references (Fortran does not maintain reference counters). Caution about lifetimes, in the second snip, should the prodX pointer reside in a module, and the prod1&2 reside in the subroutine, reference of prodX after return from subroutine Encapsulate is undefined (due to in this case of the pointee being deallocated but the pointer not being nullified).

Jim Dempsey

0 Kudos
Ilie__Daniel
Beginner
580 Views

Sure Jim. Fortran does not have garbage collection, so no reference counters are present. Thank you for the advice on the actual scope of the variables. I think I was not sufficiently clear in my original post.

In my example, I went for an OO approach to defining the factory. Specifically, the factory class has the polymorphic product (must be a pointer) as a field/property and two type bound procedures for handling the creation and clean-up:

  1. The creation procedure holds the switch, in a similar fashion as your example, and performs a typed allocation on the polymorphic property (the pointer). I believe that this creates an unnamed target object of the same type and immediately associates it with the pointer. This pointer is returned to the main code, which uses it correctly, as required. All fine so far.
  2. The main code sees the actual instanced factory and a  polymorphic product pointer. Now the polymorphic product pointer is associated with the allocated pointer at Step 1. Fine again.
  3. The factory performs the clean-up on its polymorphic field, by checking if it is associated (answer is yes), and then deallocating it. At his stage, I expect two things: firstly, the typed unnamed object should be finalized according to its type implementation (this does not happen) and secondly the polymorphic field is nullified (this happens).
  4. Back in the main code the polymorphic product pointer is nullified, too.

All in all, there is a unnamed object somewhere which cannot be reached anymore.

My question is: Is this a programmer's error? What have I done wrong?

Thank you for your insight into this.

0 Kudos
IanH
Honored Contributor II
580 Views

Are you using a current compiler?


>dir *.f90 /b | ff08depends - > compile-order.txt


>ifort /check:all /warn:all /standard-semantics /Fefactory-test.exe @compile-order.txt
ifort /warn:all /standard-semantics /Fefactory-test.exe abstract.f90 product1.f90 product2.f90 factory.f90 main.f90

Intel(R) Visual Fortran Intel(R) 64 Compiler for applications running on Intel(R) 64, Version 17.0 Build 20161005
Copyright (C) 1985-2016 Intel Corporation.  All rights reserved.

product1.f90(30): remark #7712: This variable has not been used.   [THIS]
    subroutine execute_sub(this)
---------------------------^
product1.f90(20): remark #7712: This variable has not been used.   [THIS]
    subroutine clean(this)
---------------------^
product2.f90(30): remark #7712: This variable has not been used.   [THIS]
    subroutine execute_sub(this)
---------------------------^
product2.f90(20): remark #7712: This variable has not been used.   [THIS]
    subroutine clean(this)
---------------------^
Microsoft (R) Incremental Linker Version 14.00.24215.1
Copyright (C) Microsoft Corporation.  All rights reserved.

-out:factory-test.exe
-subsystem:console
abstract.obj
product1.obj
product2.obj
factory.obj
main.obj


>factory-test.exe 1
 Factory: Creating Product 1.
 Factory: Creation success.
 Product 1: Using.
 Product 1: Destroying.
 Factory: Destroying product success.

 

0 Kudos
Ilie__Daniel
Beginner
580 Views

Ian,

You are definitely are getting what I was expecting. I think you may be on to something, because I use

Compiling with Intel(R) Visual Fortran Compiler XE 12.1.1.258 [IA-32]...

Could I ask you to build and run with the IA-32 (your version)?

Please let me know what you get.

Thank you for your help.

 

 

0 Kudos
andrew_4619
Honored Contributor II
580 Views

Full 2003 support is only 16.0 onwards and there have been many bug fixes since. I think you will find many other oo problems with XE 12.1.1.258 [IA-32]... you really need to upgrade.

0 Kudos
IanH
Honored Contributor II
580 Views

I get the same with the IA-32 compiler. 

I second Andrew's comments.  You need a current compiler if you are going to rely on this stuff.

0 Kudos
Reply