Search code examples
fortranfortran90intel-fortran

Proper way to pass pointers into many subroutines


I'm not a very good programmer and I'm just trying to interface with a model that provides data as pointers. These pointers are passed down through several subroutines before data is written to them. I'm not sure how to do this so that I avoid memory leaks.

Let's say I have an array pointer A that is passed to several subroutines before being written to, how do I handle the declarations, allocations, and deallocations?

module data

implicit none
contains 

subroutine s1(a)
real, pointer, intent(out) :: a(5,5)

call s2(a)
end subroutine s1

subroutine s2(a)
real, pointer, intent(out) :: a(5,5)
integer :: i 

do i = 1,5 
  a(:,i) = 5.0
end do
end subroutine s2
end module data

Program test
use data, only : s1, s2
real, pointer, dimension(:,:) :: A => NULL()
allocate(A(5,5))
call s1(A)
write(*,*) A
deallocate(A)
end Program test

Solution

  • Please note that your code is not Fortran 90. The intent attribute for dummy (formal) arguments that are pointers was introduced in Fortran 2003.

    The intent refers to the association status of the pointer, not to its target. Also, if the argument is a derived type with pointer components, the intent applies to the type object itself, not the targets of the pointers. That is, if, for example, intent(in) is used, the data area that the pointer is targeted at can be modified:

    module MyType_mod
    
      implicit none
      private
    
      type, public :: MyType
         integer, pointer :: ptr(:)
       contains
         procedure :: sub => my_type_sub
      end type MyType
    
    contains
    
      subroutine my_type_sub(self)
        ! Dummy argument
        class(MyType), intent(in) :: self
    
        ! The following is perfectly legal,
        ! even though intent(in) was specified
        self%ptr = 42
    
      end subroutine my_type_sub
    
    end module MyType_mod
    
    program main
    
      use MyType_mod, only: &
           MyType
    
      implicit none
    
      type(MyType) :: foo
      integer      :: alloc_stat
    
      allocate( integer :: foo%ptr(100), stat=alloc_stat )
      call foo%sub()
    
    end program main
    

    Even though not required, in a case such as the previous example, it is better to state intent(inout) to indicate to the reader that modification of data is taking place.

    On another note, you may find this answer useful Fortran subroutine returning wrong values