passing pointer to subroutine

passing pointer to subroutine

Hi all,

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

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

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

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?

publicaciones de 11 / 0 nuevos
Último envío
Para obtener más información sobre las optimizaciones del compilador, consulte el aviso sobre la optimización.

Cita:

Johannes escribió:

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
Cita:

Johannes escribió:

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

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.

www.quickthreadprogramming.com

Cita:

jimdempseyatthecove escribió:

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.

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

www.quickthreadprogramming.com

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.

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

Adjuntos: 

AdjuntoTamaño
Descargar undefined-pointer-array.jpg104.07 KB

What you should consider is passing into the subroutine
subroutine sub_ptr(b)
real, dimension (:), allocatable, intent(out):: b
Jim Dempsey

www.quickthreadprogramming.com

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

@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

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

Deje un comentario

Por favor inicie sesión para agregar un comentario. ¿No es socio? Únase ya