- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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.
Link Copied
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
>> 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
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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:
- 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.
- 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.
- 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).
- 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.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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.
- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page