How to pass allocatable arrays to subroutines in Fortran

前端 未结 3 1885
日久生厌
日久生厌 2020-11-27 06:38

The following code is returning a Segmentation Fault because the allocatable array I am trying to pass is not being properly recognized (size returns 1, when it should be 3)

相关标签:
3条回答
  • 2020-11-27 07:18

    If a procedure has a dummy argument that is an allocatable, then an explicit interface is required in any calling scope.

    (There are numerous things that require an explicit interface, an allocatable dummy is but one.)

    You can provide that explicit interface yourself by putting an interface block for your subroutine inside the main program. An alternative and far, far, far better option is to put the subroutine inside a module and then USE that module in the main program - the explicit interface is then automatically created. There is an example of this on the eng-tips site that you provided a link to - see the post by xwb.

    Note that it only makes sense for a dummy argument to have the allocatable attribute if you are going to do something related to its allocation status - query its status, reallocate it, deallocate it, etc.

    0 讨论(0)
  • 2020-11-27 07:22

    This is a simple example that uses allocatable dummy arguments with a module.

    module arrayMod   
      real,dimension(:,:),allocatable :: theArray    
    end module arrayMod
    
    program test
       use arrayMod
       implicit none
    
       interface
          subroutine arraySub
          end subroutine arraySub
       end interface
    
       write(*,*) allocated(theArray)
       call arraySub
       write(*,*) allocated(theArray) 
    end program test
    
    subroutine arraySub
       use arrayMod
    
       write(*,*) 'Inside arraySub()'
       allocate(theArray(3,2))
    end subroutine arraySub
    
    0 讨论(0)
  • 2020-11-27 07:24

    Please also note that your allocatable dummy argument array is declared with intent(in), which means its allocation status will be that of the associated actual argument (and it may not be changed during the procedure). The actual argument passed to your subroutine may be unallocated and therefore illegal to reference, even with an explicit interface. The compiler will not know this and the behaviour of inquiries like size is undefined in such cases.

    Hence, you first have to check the allocation status of array with allocated(array) before referencing its contents. I would further suggest to implement loops over the full array with lbound and ubound, since in general you can't be sure about array's bounds:

    subroutine subtest(array)
      double precision, allocatable, intent(in) :: array(:,:)
      integer                                   :: iii, jjj
    
      if(allocated(array)) then
        print*, size(array, 1), size(array, 2)
        do iii = lbound(array, 1), ubound(array, 1)
          do jjj = lbound(array, 2), ubound(array, 2)
            print*, array(iii,jjj)
          enddo
        enddo
      endif  
    end subroutine
    
    0 讨论(0)
提交回复
热议问题