Passing unallocated allocatable variable as an allocatable dummy argument

Viewed 174

In the following program, an allocatable variable x is passed to a subroutine test_sub without being allocated. The corresponding allocatable dummy variable x_sub is allocated in test_sub:

module test_mod

    implicit none

    contains

        subroutine test_sub(x_sub)

            implicit none
            real, allocatable :: x_sub(:)

          ! Execution !

!           return
            allocate(x_sub(1))
!           deallocate(x_sub)

        end subroutine test_sub

end module test_mod

program test

    use test_mod, only: test_sub
    implicit none
    real, allocatable :: x(:)

  ! Execution !

    print*, 'Before call to sub', allocated(x)
    call test_sub(x)
    print*, 'After call to sub', allocated(x)

end program test

When control is returned to the main program, x is allocated:

 Before call to sub F
 After call to sub T

If test_sub returns before allocating x_sub, or if x_sub is deallocated before returning, x is not allocated:

 Before call to sub F
 After call to sub F

I observe this behavior using both gfortran 4.4.7 and ifort 19.0.

My question is whether this is standard behavior. I would have expected to get a segfault when trying to pass x without it being allocated. I'm worried this behavior might lead to unexpected results in larger programs.

3 Answers

You can use an intent declaration to control the allocation behavior of your variable inside the routine:

  1. real, allocatable, intent(inout) :: x(:) is equivalent to your case.

    • Allocation status is not known a priori, it can be tested with allocated(x);
    • Allocation status can change using allocate/deallocate
  2. if real, allocatable, intent(in) :: x(:), then the allocation status cannot change inside of it;

    • Can test allocation status using allocated(x)
    • Can not modify it
  3. if real, allocatable, intent(out) :: x(:), then variable x is always initialized as non-allocated, regardless of its former status before calling the routine, so you can always begin your subroutine with allocate(x(n)).

I believe you're using option 1) but you want 3).

This is standard behavior. The dummy argument being allocatable has no implications that the variable needs to be allocated on input or output. It just means that the variable is allocatable such that you can treat it as an allocatable inside of that function, e.g. implicit reallocation and such.

To find out whether it is allocated aitomatically, you should print it inside the subroutine, before executing your own allocate. There is no automatic allocation taking place.

It is perfectly fine to pass a non-allocated allocatable to an allocatable dummy argument. It is passed as "not allocated".

Related