- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Compiling (with ifort 13.1.1) and executing the following code
[fortran]
module tt
type :: t
end type t
type :: t1
class(t), pointer :: tp
contains
procedure :: set
procedure :: unset
end type t1
contains
function t_new() result(r)
type(t), pointer :: r
allocate(r)
end function t_new
subroutine set(a, tp)
class(t1) :: a
class(t), target :: tp
a%tp => tp
end subroutine set
subroutine unset(a)
class(t1) :: a
print *, "Dealocating"
deallocate(a%tp)
print *, "Deallocated"
end subroutine unset
end module tt
program test
use tt
type(t1) :: a
call a%set(t_new())
call a%unset()
end program test
[/fortran]
I get
[plain]
Dealocating
forrtl: severe (173): A pointer passed to DEALLOCATE points to an object that cannot be deallocated
Image PC Routine Line Source
pointer 000000000046D7AE Unknown Unknown Unknown
pointer 000000000046C246 Unknown Unknown Unknown
pointer 0000000000424FC2 Unknown Unknown Unknown
pointer 00000000004068BB Unknown Unknown Unknown
pointer 00000000004050E6 Unknown Unknown Unknown
pointer 0000000000402C57 Unknown Unknown Unknown
pointer 0000000000402B3C Unknown Unknown Unknown
libc.so.6 00007FB324690A15 Unknown Unknown Unknown
pointer 0000000000402A39 Unknown Unknown Unknown
[/plain]
but using gfortran yields
[plain]
Dealocating
Deallocated
[/plain]
Is this a bug?
Best,
Paweł Biernat
Link Copied
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Yes, it is a bug. I have escalated it as issue DPD200243572. A workaround is to have t_new return a class(t) pointer that is allocated as type(t), for example:
[fortran]
function t_new() result(r)
class(t), pointer :: r
allocate(t::r)
end function t_new
[/fortran]
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi Steven,
I am wondering how this type of function, what returns a pointer as result that is allocated locally, can avoid memory leak by proper deallocating. I have an application of such pattern in a recursive function. Many thanks.
You
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
@Lu__You , this is entirely the programmer's responsibility. Fortran doesn't give you any help here.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
@Steve_Lionel
Thank you. Surely it is. But is it even possible in theory to deallocate such result pointers in Fortran? I would appreciate it if you have any suggestions.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Of course. Assuming you use pointer assignment and not intrinsic assignment:
program test
implicit none
integer, pointer :: p => null()
p => f(3)
print *, associated(p), p
deallocate (p)
print *, associated(p)
contains
function f(x)
integer, pointer :: f
integer, intent(in) :: x
allocate (f)
f = x
return
end function f
end program test
T 3
F
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Thank you for the quick response.
Sorry I forgot to make it clear that I was just using the intrinsic allocate function, something like:
recursive function returnScalar(meta) result(val)
class(*), pointer :: val
allocate(val, source=returnScalar(meta%next))
...
But it's also very helpful to confirm that such implementation can't avoid a leak. Thank you very much.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Yes, it CAN leak. It's up to you to make sure it doesn't.
Your question is not really related to this thread, however.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Apologies for digressing! But thanks a lot for the discussion!
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
@Steve_Lionel wrote:
.. Your question is not really related to this thread, however.
@Yu__Lou wrote:
Apologies for digressing! But thanks a lot for the discussion!
@Lu__You ,
You're on the right track in thinking about memory leak issues in codes that do allocations in recursive functions the way you show in a brief snippet.
As implied by @Steve_Lionel comment, your concerns are worth for a different thread.
And indeed such a thread can involve code design aspects as well as modern Fortran language facilities.
A good place for such a discussion will be the Fortran Discourse site at:
https://fortran-lang.discourse.group/
I suggest you open up a thread at this Discourse site and share as much details regarding the code you have in mind with recursive functions, unlimited polymorphic object with POINTER attribute, and possible a linked list like derived type.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Thank you for the suggestion. It's indeed a good idea to have some discussions there!--It's more about intrinsic limits of the current Fortran language standards.
In fact I am following the current thread because I'm having a similar difficulty of deallocating pointers to unlimited polymorphic components of a derived type. (It's another concern of memory leak!) It segfaults as of 17.0.2. Then I happened to see @Steve_Lionel's snippet code of returning a pointer in a similar concept of my memory-leaking implementation. Lol
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
OOPS, I wrote the following before seeing the above post.
Ignore the following (as you are using TBP)
>> I'm having a similar difficulty of deallocating pointers to unlimited polymorphic components of a derived type.
The above states that you have an external (to the derived type) pointer to an allocatable within the derived type.
Should this component be ALLOCATABLE, it would also have to have the TARGET attribute .AND. the (external) pointer could not deallocate this component.
Should this component be POINTER (which is/was allocated), then the external pointer could perform the deallocate **** with your requirement to NULLIFY the component pointer, and all other pointers that may be pointing to that component.
You would be best served by creating a type bound function/subroutine to perform this.
Type-Bound Procedures (intel.com)
Jim Dempsey
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Thanks, I will use the workaround.
Paweł
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Steve,
Why is scoping required on the allocate?
Jim Dempsey
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Jim, if you mean the t::, that specifies the dynamic type of the allocated polymorphic object. It is not strictly necessary in this case, as without it the declared type t is used anyway, but I like to put it in there for clarity when allocating a polymorphic object.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
An alternative workaround, and one I think is "more correct", is to make the tp argument to set a pointer rather than target. The problem is that anything could be a target and not necessarily something that was allocated. We need to look at this closer and it may be a while before we have an answer. But regardless, I think pointer is the right thing to use in set.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
In F2003 (specifically), can the value that results from the evaluation of an expression have the target attribute?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
So is the statement
[fortran]
call a%set(t_new())
[/fortran]
valid in F2008 at all? Should I avoid using the result of a function as an argument this way and introduce temporary variable instead?
[fortran]
class(t), pointer :: tmp
tmp=>t_new()
call a%set(tmp)
[/fortran]
Paweł
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
That specific statement is valid F2003/F2008, the problem is what happens afterwards, particularly when the set procedure finishes. I think in F2003 the pointer association status of the tp component becomes undefined - this is because the dummy argument that it is pointed at is associated with an actual argument that is an expression, as part of the call that expression is evaluated, evaluation of an expression produces a value, as Steve says - a value cannot be a target, when you have a non-target actual associated with a target dummy the pointer association status of things pointed at the dummy becomes undefined when the procedure terminates.
In F2008 a variable can be a function reference that has a data pointer result (which I don't think ifort does yet, but I think gfortran does). A variable can be a target - whatever the function result points at has to have had the target attribute. So you have a target actual with a target dummy. So things are ...umm... different. After that - I get confused and give up. Part of my confusion resulted in a post to c.l.f.
Edit to note that the first paragraph above is all wrong. See interp F95/0074 case 3.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Dear all,
Does anyone working at intel know the status of this issue? is there a plan to fix it?
I run into the same issue with the last version of the intel compiler (2019). Even though the workaround of using a class(t) pointer that is allocated as type(t) works, it makes some code harder to read and to write since a "select type" is needed when working on the pointer.
EDIT: my bad, I didn't understand the workaround properly, select type is indeed not needed.

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