question about ALLOCATABLE arrays

Hi All,

Does this program do a Bad Thing?

PROGRAM myprog
REAL*8, ALLOCATABLE  :: arry1(:)
REAL*8, ALLOCATABLE  :: arry2(:)
REAL*8, ALLOCATABLE  :: arry3(:)
REAL*8               :: ans
INTEGER              :: iflag,ilength
!
WRITE(*,*)'enter the flag'
READ(*,*)iflag
!
IF(iflag = 1)THEN
  CALL getlength1(ilength)
  ALLOCATE(arry1(ilength))
END IF
!
IF(iflag = 2)THEN
  CALL getlength2(ilength)
  ALLOCATE(arry2(ilength))
END IF
!
IF(iflag = 3)THEN
  CALL getlength3(ilength)
  ALLOCATE(arry3(ilength))
END IF
!
CALL mysub(iflag,ilength,arry1,arry2,arry3,ans)
!
END PROGRAM myprog
!
!
!
SUBROUTINE mysub(iflag,ilength,arry1,arry2,arry3,ans)
!
IMPLICIT NONE
INTEGER, INTENT(IN)    :: iflag
INTEGER, INTENT(IN)    :: ilength
REAL*8, INTENT(IN)     :: arry1(ilength)
REAL*8, INTENT(IN)     :: arry2(ilength)
REAL*8, INTENT(IN)     :: arry3(ilength)
REAL*8, INTENT(OUT)    :: ans
!
IF (iflag = 1)THEN
  < compute things using arry1 only >
  ans = result_of_computation
  RETURN
END IF
!
IF (iflag = 2)THEN
  < compute things using arry2 only >
  ans = result_of_computation
  RETURN
END IF
IF (iflag = 3)THEN
  < compute things using arry3 only >
  ans = result_of_computation
  RETURN
END IF
!
END SUBROUTINE mysub

The user chooses an option, and based on that option, an array is ALLOCATED (with a length that depends on the option) and is then passed to a subroutine. This subroutine executes statements using only the corresponding array in the main program that was ALLOCATED. The subroutine has as arguments all of the arrays for all available options.

My actual code seems to run fine, but valgrind might be getting confused. What are the rules about passing an array that was not ALLOCATED into a subroutine?

Thanks,

Jerry

Hi Jerry,

I think it’s fine given you’re guarding access to the unallocated arrays, but it’s probably not really the best way to do this.

Instead, I would suggest adding an interface for “mysub” (either explicitly or by putting it into a module) and then changing the declaration of the arrays to:

REAL*8, ALLOCATABLE, INTENT(IN)     :: arry1(:)
REAL*8, ALLOCATABLE, INTENT(IN)     :: arry2(:)
REAL*8, ALLOCATABLE, INTENT(IN)     :: arry3(:)

Right now you’re using F77 style calling conventions so just passing in pointers, two of which are uninitialized, which is what Valgrind is most likely complaining about. With an interface, you’ll be using F90 calling conventions so will be passing in a descriptor for the arrays and thus be able to check their allocation status. This should quiet Valgrind as well.

Hope this helps,
Mat

Hi Mat,

Thanks for the response. I “fixed” the problem by giving the unused arrays a length of 1 in the main program, and passing separate lengths for the arrays into the subroutine.

I am starting the process of learning about interfaces and modules, and it probably would be better to practice on smaller codes to start with.

Jerry