- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
The test code is as bellow:
After compiling, and running with the valgrind, there's the memory leakage
==2160== 16 bytes in 1 blocks are definitely lost in loss record 3 of 3
==2160== at 0x4C2993D: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==2160== by 0x4006D3: __datamod_MOD_dataadd (test.f90:21)
==2160== by 0x4007D1: MAIN__ (test.f90:43)
==2160== by 0x400820: main (test.f90:32)
How to avoid this leakage?
[bash] 1 module DataMOD 2 type data 3 real :: x 4 type(data),pointer :: next 5 end type data 6 7 interface operator(+) 8 module procedure DataAdd 9 end interface operator(+) 10 11 contains 12 13 recursive function DataAdd( d1, d2) result(d) 14 implicit none 15 type(data),intent(in) :: d1, d2 16 type(data) :: d 17 type(data),pointer :: pd1, pd2, pd 18 19 d%x = d1%x + d2%x 20 if(associated(d1%next))then 21 allocate(d%next) 22 pd1 => d1%next 23 pd2 => d2%next 24 pd => d%next 25 pd = pd1 + pd2 26 endif 27 end function DataAdd 28 29 end module DataMOD 30 31 program test 32 use DataMOD 33 implicit none 34 35 type(data) :: d1, d2, d 36 37 allocate(d1%next, d2%next) 38 d1%next%x = 3. 39 d2%next%x = 4. 40 41 d = d1 + d2 42 end program test[/bash]
After compiling, and running with the valgrind, there's the memory leakage
==2160== 16 bytes in 1 blocks are definitely lost in loss record 3 of 3
==2160== at 0x4C2993D: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==2160== by 0x4006D3: __datamod_MOD_dataadd (test.f90:21)
==2160== by 0x4007D1: MAIN__ (test.f90:43)
==2160== by 0x400820: main (test.f90:32)
How to avoid this leakage?
Link Copied
8 Replies
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Objects to which pointers point are not auto-deallocated when the pointer "expires" (exit function/subroutine containing local pointer, or exiting function/subroutine containing local object containing pointer(your case), ordeallocating object containing pointer). Basically the same functionality that happens in C/C++.
Look in the IVF documentationfor FINAL. You can use FINAL subroutine(s) to perform cleanup operations upon object distruction (deallocate or exiting scope of life of object (including temporaryobject as result from expression)).
*** caution ***
Ensure that no more than one data%next points to the same object.
Also, (not affecting memory leak) IF block on line 20 assumes if d1%next is associated that d2%next is also associated. This may or may not be true. You should handle that condition or issue an assert fail.
Jim Dempsey
Look in the IVF documentationfor FINAL. You can use FINAL subroutine(s) to perform cleanup operations upon object distruction (deallocate or exiting scope of life of object (including temporaryobject as result from expression)).
*** caution ***
Ensure that no more than one data%next points to the same object.
Also, (not affecting memory leak) IF block on line 20 assumes if d1%next is associated that d2%next is also associated. This may or may not be true. You should handle that condition or issue an assert fail.
Jim Dempsey
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
What I mean is that the operator function "DataAdd" has the memory
leakage, and how to deallocate this?
leakage, and how to deallocate this?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
First of all, valgrind will often report memory leaks that are not really there in Fortran programs because it does not understand Fortran memory management. Second, there is an error in your code in that you do not give pointer component next an initial NULL() value - this makes the ASSOCIATED test on it invalid. One fix would be to change the component declaration to:
type(data),pointer :: next => null()
When I make this change and run it with Intel Inspector XE, I find no memory leaks in the program.
type(data),pointer :: next => null()
When I make this change and run it with Intel Inspector XE, I find no memory leaks in the program.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Steve,
The user has a memory leak due to programming error.
d, declared at line 16 (but represents in this case d declared at line 35), gets a data object allocated to its next at line 21. There is no corrisponding deallocate to that d's next pointer.
Had the user looked at my message regarding FINAL, they would find outthat he can create a FINAL subroutine for his data object (type) that can deallocate the object pointed to by its next pointer.
Note, he should have the => NULL in the constructor as you suggest.
Jim Dempsey
The user has a memory leak due to programming error.
d, declared at line 16 (but represents in this case d declared at line 35), gets a data object allocated to its next at line 21. There is no corrisponding deallocate to that d's next pointer.
Had the user looked at my message regarding FINAL, they would find outthat he can create a FINAL subroutine for his data object (type) that can deallocate the object pointed to by its next pointer.
Note, he should have the => NULL in the constructor as you suggest.
Jim Dempsey
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I'v modified the code as bellow.
please give me some clue.
If i don't want to use "FINAL Subroutine", how should I modify the code by manual deallocate?
[bash]module DataMOD type data real :: x type(data),pointer :: next=>null() contains FINAL :: RemoveData end type data interface operator(+) module procedure DataAdd end interface operator(+) contains recursive function DataAdd( d1, d2) result(d) implicit none type(data),intent(in) :: d1, d2 type(data) :: d type(data),pointer :: pd1, pd2, pd d%x = d1%x + d2%x if(associated(d1%next))then allocate(d%next) pd1 => d1%next pd2 => d2%next pd => d%next pd = pd1 + pd2 endif end function DataAdd recursive function trans(d) result(od) implicit none type(data),intent(in) :: d type(data) :: od od%x = d%x + 5. if(associated(d%next))then allocate(od%next) od%next = trans(d%next) endif end function trans recursive subroutine RemoveData(D) implicit none type(data) :: D if(associated(D%next)) call RemoveData(D%next) deallocate(D%next) write(*,*)"RemoveData" end subroutine RemoveData subroutine ddd ! use DataMOD implicit none type(data) :: d1, d2, d, dd d1%x = 1. d2%x = 2. allocate(d1%next, d2%next) d1%next%x = 3. d2%next%x = 4. d = d1 + d2 dd = trans(d1) end subroutine ddd end module DataMOD program test use DataMOD call ddd end program test [/bash]There's also some error: *** glibc detected *** ./a.out: double free or corruption (fasttop): 0x0000000001da20a0 ***.
please give me some clue.
If i don't want to use "FINAL Subroutine", how should I modify the code by manual deallocate?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
"double free" the same object being returned (deallocated)twice. I suggest you add trace code to aid you in following what is happening. Look for object copy operations (=) where a pointer might get duplicated.
Also, your DataAdd and trans functionsassume the first level next pointers are null. While this may be true in your subroutine ddd. It may not be true for general use in your application. You may need to directly call your FINAL routine to properly cleanup the prior allocations prior to making new allocations.
DataAdd:
if(associated(d%next)) RemoveData(d)
allocate(d%next)
trans:
if(associated(od%next)) RemoveData(od)
allocate(od%next)
Don't omit tracing. Add it as conditional code.
Jim Dempsey
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Sir,
Again as your direct, the code is modified as bellow:
After run in valgrind, the memory leakage errors are:
==6470== 16 bytes in 1 blocks are definitely lost in loss record 1 of 2
==6470== at 0x4C2993D: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==6470== by 0x400D42: __datamod_MOD_dataadd (test.f90:28)
==6470== by 0x400999: __datamod_MOD_ddd (test.f90:82)
==6470== by 0x400E10: MAIN__ (test.f90:97)
==6470== by 0x400E46: main (test.f90:95)
==6470==
==6470== 16 bytes in 1 blocks are definitely lost in loss record 2 of 2
==6470== at 0x4C2993D: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==6470== by 0x400B9F: __datamod_MOD_trans (test.f90:55)
==6470== by 0x4009E6: __datamod_MOD_ddd (test.f90:84)
==6470== by 0x400E10: MAIN__ (test.f90:97)
==6470== by 0x400E46: main (test.f90:95)
==6470==
==6470== LEAK SUMMARY:
==6470== definitely lost: 32 bytes in 2 blocks
==6470== indirectly lost: 0 bytes in 0 blocks
==6470== possibly lost: 0 bytes in 0 blocks
==6470== still reachable: 0 bytes in 0 blocks
==6470== suppressed: 0 bytes in 0 blocks
how to avoid these memory leakage without using the FINAL subroutine? how to modified the above code?
Again as your direct, the code is modified as bellow:
[bash]module DataMOD type data real :: x type(data),pointer :: next=>null() ! contains ! FINAL :: RemoveData end type data interface operator(+) module procedure DataAdd end interface operator(+) interface assignment(=) module procedure DataAssign end interface assignment(=) contains recursive function DataAdd( d1, d2) result(d) implicit none type(data),intent(in) :: d1, d2 type(data) :: d type(data),pointer :: pd1, pd2, pd d%x = d1%x + d2%x if(associated(d1%next))then call RemoveData(d) allocate(d%next) pd1 => d1%next pd2 => d2%next pd => d%next pd = pd1 + pd2 endif end function DataAdd recursive subroutine DataAssign(od, id) implicit none type(data),intent(in) :: id type(data),intent(out) :: od od%x = id%x if(associated(id%next))then call RemoveData(od) allocate(od%next) call DataAssign(od%next, id%next) endif end subroutine DataAssign recursive function trans(d) result(od) implicit none type(data),intent(in) :: d type(data) :: od od%x = d%x + 5. if(associated(d%next))then call RemoveData(od) allocate(od%next) od%next = trans(d%next) endif end function trans recursive subroutine RemoveData(D) implicit none type(data) :: D if(associated(D%next)) then call RemoveData(D%next) deallocate(D%next) endif write(*,*)"RemoveData" end subroutine RemoveData subroutine ddd ! use DataMOD implicit none type(data) :: d1, d2, d, dd d1%x = 1. d2%x = 2. allocate(d1%next, d2%next) d1%next%x = 3. d2%next%x = 4. d = d1 + d2 dd = trans(d1) call RemoveData(d1) call RemoveData(d2) call RemoveData(d) call RemoveData(dd) end subroutine ddd end module DataMOD program test use DataMOD call ddd end program test [/bash]
After run in valgrind, the memory leakage errors are:
==6470== 16 bytes in 1 blocks are definitely lost in loss record 1 of 2
==6470== at 0x4C2993D: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==6470== by 0x400D42: __datamod_MOD_dataadd (test.f90:28)
==6470== by 0x400999: __datamod_MOD_ddd (test.f90:82)
==6470== by 0x400E10: MAIN__ (test.f90:97)
==6470== by 0x400E46: main (test.f90:95)
==6470==
==6470== 16 bytes in 1 blocks are definitely lost in loss record 2 of 2
==6470== at 0x4C2993D: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==6470== by 0x400B9F: __datamod_MOD_trans (test.f90:55)
==6470== by 0x4009E6: __datamod_MOD_ddd (test.f90:84)
==6470== by 0x400E10: MAIN__ (test.f90:97)
==6470== by 0x400E46: main (test.f90:95)
==6470==
==6470== LEAK SUMMARY:
==6470== definitely lost: 32 bytes in 2 blocks
==6470== indirectly lost: 0 bytes in 0 blocks
==6470== possibly lost: 0 bytes in 0 blocks
==6470== still reachable: 0 bytes in 0 blocks
==6470== suppressed: 0 bytes in 0 blocks
how to avoid these memory leakage without using the FINAL subroutine? how to modified the above code?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
RemoveData must NULLIFY D%next after deallocate of D%next
As your code is currently written, the top most levelremains non-NULL at point of return from subroutine ddd, and thus when FINAL is run on d1, d2, d, dd those nodes's %nextwill be deallocated a second time (as well as the now junk data in what appears to be in those next pointer, etc....
The calls to RemoveData on lines 85:88 should not be required since when you return from ddd, the FINAL subroutine will be automatically called for d1, d2, d, dd.
As per earlier post, add trace code to observe what is going on
allocate(od%next)
write(*,*) 'ddd allocate', loc(od), loc(od%next)
...
write(*,*) 'RemoveData deallocate', loc(D), loc(D%next)
deallocate(D%next)
insert similar code in all places of allocation and deallocations, annotate write with function/subroutine name as above. Use FORMAT statement to display loc in Hex such that you can corrilate addresses with valgrind (or use calculator for conversion).
By observing your trace output and comparing with valgrind you should discover an inconsistancy. Knowing the inconsistancy (object addresswho's next is being allocated to or deallocated from, you can then step through your program and when at that point in your code you can observe current state of current call stack level and eachhigher call stack level. At some point you will find the problem.
Jim Dempsey
As your code is currently written, the top most levelremains non-NULL at point of return from subroutine ddd, and thus when FINAL is run on d1, d2, d, dd those nodes's %nextwill be deallocated a second time (as well as the now junk data in what appears to be in those next pointer, etc....
The calls to RemoveData on lines 85:88 should not be required since when you return from ddd, the FINAL subroutine will be automatically called for d1, d2, d, dd.
As per earlier post, add trace code to observe what is going on
allocate(od%next)
write(*,*) 'ddd allocate', loc(od), loc(od%next)
...
write(*,*) 'RemoveData deallocate', loc(D), loc(D%next)
deallocate(D%next)
insert similar code in all places of allocation and deallocations, annotate write with function/subroutine name as above. Use FORMAT statement to display loc in Hex such that you can corrilate addresses with valgrind (or use calculator for conversion).
By observing your trace output and comparing with valgrind you should discover an inconsistancy. Knowing the inconsistancy (object addresswho's next is being allocated to or deallocated from, you can then step through your program and when at that point in your code you can observe current state of current call stack level and eachhigher call stack level. At some point you will find the problem.
Jim Dempsey

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