Intel® Fortran Compiler
Build applications that can scale for the future with optimized code designed for Intel® Xeon® and compatible processors.
Announcements
FPGA community forums and blogs on community.intel.com are migrating to the new Altera Community and are read-only. For urgent support needs during this transition, please visit the FPGA Design Resources page or contact an Altera Authorized Distributor.

passing pointer to subroutine

Johannes_Rieke
New Contributor III
2,540 Views

Hi all,

I'm new in the field of pointers and I wonder a little bit on one thing. Here is my example:

[fortran]

program main_program
  interface
     subroutine sub_ptr(b)
     real, dimension (:), pointer :: b
     end subroutine sub_ptr
  end interface
!   
  real, dimension (:), pointer :: a
!         
  call sub_ptr(a)
  write(*,'(<size(a)>f6.2)') a
end program main_program

[/fortran]

[fortran]

subroutine sub_ptr(b)
  real, dimension (:), pointer :: b
  real, dimension (:), allocatable, target  :: c
  integer, parameter           :: m = 5
  integer                      :: i
 
  allocate (b(m))
  allocate (c(m))
  do i = 1, m
    c(i) = float(i)
  end do
  b = c   ! this is how it works
  !b => c  ! this is how it not works
  continue
end subroutine sub_ptr

[/fortran]

If I assign b to c by => in the subroutine, the result of a in the main program is garbage. Doing the same just with the equal sign, a contains the expected data...

Is this caused by the fact, that all variables of the subroutine are freed, if the subroutine is finished? Then the pointer points into nirvana?

Best regards, Johannes

ps: In ifort XE 12.1.6.369 and VS 2010 SP1 the array c is not correctly shown in debug mode, when hovering the mouse on it: "Undefined pointer/ array" Also in watch window. Is this a bug?

0 Kudos
10 Replies
Anonymous66
Valued Contributor I
2,540 Views
Johannes wrote:

If I assign b to c by => in the subroutine, the result of a in the main program is garbage. Doing the same just with the equal sign, a contains the expected data...

Is this caused by the fact, that all variables of the subroutine are freed, if the subroutine is finished? Then the pointer points into nirvana?

Yes. If you want the target to stick around after the routine is done, add the save attribute
Johannes wrote:

ps: In ifort XE 12.1.6.369 and VS 2010 SP1 the array c is not correctly shown in debug mode, when hovering the mouse on it: "Undefined pointer/ array" Also in watch window. Is this a bug?

If you are hovering over the array c before it has been allocated, it is indeed undefined. The memory for c has not been allocated yet. This is not a bug. Regards, Annalee Intel Developer Support
0 Kudos
jimdempseyatthecove
Honored Contributor III
2,540 Views
In sub_ptr c(:) is a local allocatable. This will be deallocated on exit of the subroutine. Making b => c point to unallocated memory (previously allocated) The b = c format (when realloc lhs in effect) will allocate caller's b via the subrotine reference to b.
0 Kudos
JVanB
Valued Contributor II
2,541 Views
jimdempseyatthecove wrote:

The b = c format (when realloc lhs in effect) will allocate caller's b via the subrotine reference to b.

Not here. That only works if b is an allocatable, not a pointer. In the above example, if b doesn't have a target the same shape is c, then the assignment is an error. But in that example b did receive a target (via allocation) so the ordinary assignment works. With pointer assignment, memory is leaked because the target b received by allocation no longer has any pointer to it. This could be fixed by simply not allocating a target for b before the pointer assignment. As has been mentioned previously, this could be fixed by giving local variable c in subroutine sub_ptr the SAVE attribute, but this could get complicated if subroutine sub_ptr were called again. First, the allocation of c would be an error, and then if c were first deallocated, pointer a in program main_program would have undefined allocation status, or if c were used without reallocating, it couldn't take on a different shape after the first call and the target of pointer a in program main_program would be mysteriously altered. Maybe it's best to simply declare c as a pointer or work with b directly.
0 Kudos
jimdempseyatthecove
Honored Contributor III
2,541 Views
b is a dummy argument that references a (:) pointer provided by the caller. The => in sub_ptr constructs in the callers pointer a(:), but used by reference locally and known as b, a descriptor to point to the allocated array c(:). c(:) is free'd upon return from sub_ptr, however the caller's pointer is not affected. Meaning, the caller's pointer a(:) points to free'd memory. This is not a case of a memory leak, rather it is the opposite (reference to free'd memory). Making c SAVE would work provided that sub_ptr is not called more than once while the return values are yet to be used. 08 real, dimension (:), pointer :: a, a2, a3 09 ! 10 call sub_ptr(a); call sub_ptr(a2); call sub_ptr(a3) ! *** all 3 returns point to the SAVE c ( last set value, which value may have changed between calls) Jim Dempsey
0 Kudos
JVanB
Valued Contributor II
2,541 Views
I don't understand why you can't see the memory leak. The sequence allocate(b(m)) b => c does in fact leak memory. Try it yourself program memleak implicit none real, pointer :: b(:) real, target, allocatable :: a(:) integer i integer, parameter :: N = 1000 allocate(a(N)) do i = 1, 1000000 allocate(b(N)) b => a call sub(b) end do end program memleak subroutine sub(x) real x(*) end subroutine sub Turn on Task Manager and watch memory usage go up.
0 Kudos
Johannes_Rieke
New Contributor III
2,541 Views
Hi all, thank you very much for the many answers. @Annalee: Unfortunately c is allocated and contains values from line 9 on in sub_ptr. I have a break point in line 12 (see attachment). In line 12 it says still "undefined pointer/array" for c. Would it be so, then sub_ptr would fail in runtime. So, I think this is a bug. @all: If I understood it right then the "SAVE" attribute is not what I want, because the sub_ptr should be called many times with different results. In this academic example it will work. But life isn't that simple and "SAVE" won't work in my complex subroutine. Or I did not understand it? A workaround could be to put sub_ptr in a module and use a global variable instead of an argument. However, the question is, whether the approach I have choosen in sub_ptr is OK ( with b = c) or cause this a memory leak? Thanks, Johannes
0 Kudos
jimdempseyatthecove
Honored Contributor III
2,541 Views
What you should consider is passing into the subroutine subroutine sub_ptr(b) real, dimension (:), allocatable, intent(out):: b Jim Dempsey
0 Kudos
Anonymous66
Valued Contributor I
2,541 Views
Hello Johannes, I am not seeing that behavior in 13.0.0.089. C is shown as allocated and containing the expected values. It appears that the bug has been fixed. Annalee
0 Kudos
Johannes_Rieke
New Contributor III
2,541 Views
@Jim: Thanks for the hint. I use the b=c declaration version in my code now together with the inten(out) and it works fine in ifort in Windows and gfortran and linux and I have not observed any memory leaks so far. @Annalee: That's nice that the bug is not also in 13.0.0.089 but as reported by others there are more dubugger issues I don't want to have. I will stay at 12.1.6.369. Will there by an update 13? Kind regards, Johannes
0 Kudos
Anonymous66
Valued Contributor I
2,541 Views
Hello Johannes, There will be an update 13, but we are not planning to port this bug fix into it. We are very careful about what we port once a newer version has been released. Regards, Annalee
0 Kudos
Reply