Silverfrost Forums

Welcome to our forums

Allocatable arrays and ENTRY not compiled correctly

27 Mar 2018 7:02 (Edited: 22 Nov 2018 12:10) #21674

The following test program displays a bug in the way that FTN95 compiles a subroutine that contains a local (unsaved) allocatable array and an ENTRY statement in a subroutine. This bug caused a failure in one of the UKRMOL codes ( https://ccpforge.cse.rl.ac.uk/gf/project/ukrmol-in/ ).

program probe
call subb()
end program

subroutine suba()
real, allocatable :: x(:)
real :: y
!
allocate (x(4))
call random_number(x)
return
!
ENTRY subb
if(allocated(x))then
   y=sum(x)
   print *,y
end if
return
end subroutine

Since SUBA was never called, the array X is never allocated and so SUBB should return without doing anything. Even if SUBA had been called, according to the Fortran standard X would have been automatically deallocated when RETURN was executed. Therefore, when SUBB is entered, X should always have a status of 'not allocated'.

Compiled with /check, the program executes the PRINT statement (it should not have done so) and exhibits an access violation in a call to __DEALLOCATE from line-18. Similar errors occur with combinations of /check, /checkmate and /64.

28 Mar 2018 1:56 #21676

There have been (probably earlier Ver5 to 7 ) problems using ALLOCATE and /CHECK where DEALLOCATE did not release the memory, but I thought with recent versions that memory management in /CHECK had changed.

I have now tried the following change to see what was happening:

! probe.f90
program probe 
call subb() 
end program 

subroutine suba() 
real, allocatable :: x(:) 
real :: y 
logical :: al
! 
allocate (x(4)) 
call random_number(x) 
return 
! 
ENTRY subb 
al = allocated (x)
if(allocated(x))then 
   y=sum(x) 
   print *,y 
end if 
return 
end subroutine 

When compiled and run using: ftn95 probe /debug /link sdbg probe with a few F7's

This shows that variable al is .false. and the program runs ok Without 'al= allocated(x)', there is a compiler bug in the way the if(...) is managed. Not sure what the problem is but using 'al =allocated(x)' shifted the problem ?

It is a strange routine

John

28 Mar 2018 2:41 #21678

I observed that the crashes occurred at the RETURN statement. Your test indicates that there is something else afoot. Perhaps, there are two out-of-sync lists of allocatable variables and their status?

Did you build with the new 8.3 compiler?

It is rather odd to see allocated variables and ENTRY statements in the same subprogram. The UKRMOL code shows signs of having been ported from old Fortran (comments in the code that indicate that conversion to F90 was performed with the help of SPAG).

28 Mar 2018 6:09 #21680

Quoted from mecej4 Did you build with the new 8.3 compiler?

No, I am still using Ver 8.20.

I switched to Ver 8.10 and the code with logical al. This appears to work ok.

I then commented out the line : !al = allocated (x) this appears to work ok

I then also commented out the line : !logical :: al this FAILS.

There must be a strange address pointer for the ENTRY for this case.

UKRMOL code must be F90 code and not F95. I wonder what else is in store ?

Hope this helps

28 Mar 2018 6:47 #21681

I have made a note that this needs investigating.

28 Mar 2018 2:13 #21687

Another clue regarding what the compiler does is the following. When the code in the first post is compiled with /checkmate and run, the EXE crashes with 'reference to undefined variable, array element or function result' on Line-13. That is a bit odd, since Line-13 contains only the ENTRY statement. I suspect that the reported line number is off, and that it is the next line that caused the 'undefined' error message.

If we take Line-14 as the actual line on which the error was detected, we have another puzzle. The message seems to indicate that the compiler thinks that the array x should be allocated and its elements defined in order to evaluate the logical expression ALLOCATED(x).

1 May 2018 11:27 #22055

Further analysis shows exactly how the bug gets created. Here is a simplified test code. The subroutine may be invoked by either the subroutine name, 'SUB' or the entry name, 'SUBA'. Since the ENTRY statement comes immediately after the declarations and there are no subroutine arguments, there should be no difference in behavior when either SUB or SUBA gets called. In particular, when the subroutine is entered, the array x(:) is unallocated.

program probe 
call suba() 
end program 

subroutine sub() 
real, allocatable :: x(:) 
real :: y
!
ENTRY suba
if(allocated(x))then
   y=sum(x) 
   print *,y 
end if 
return 
end subroutine

The bug is seen clearly in the assembly code. The crucial initialisation of the address of X to 00000000 is performed only if SUB is called, and goes missing when SUBA is called.

   0005   subroutine sub()                                                                       AT 0
 ; Start of SUBROUTINE SUB
      00000000(21/1/8)           push      ebp
      00000001(22/1/8)           mov       ebp,esp
      00000003(23/1/8)           push      ebx
      00000004(24/1/8)           push      esi
      00000005(25/1/8)           push      edi
      00000006(26/1/8)           push      eax
      00000007(27/1/8)           sub       esp,=32           ; Adjusted later if temporaries allocated
   0006   real, allocatable :: x(:)                                                              AT d
WARNING - Variable X has been used without being given an initial value
      0000000d(28/4/19)          mov       X,=0   ; <<<<<<=======
   0007   real :: y                                                                              AT 14
   0008   !                                                                                      AT 14
   0009   ENTRY suba                                                                             AT 14
      00000014(29/4/20)          jmp       __N3
                                                             ; Start of ENTRY SUBA
      00000019(31/4/20)          push      ebp
      0000001a(32/4/20)          mov       ebp,esp
      0000001c(33/4/20)          push      ebx
      0000001d(34/4/20)          push      esi
      0000001e(35/4/20)          push      edi
      0000001f(36/4/20)          push      eax               ; To align ESP on 8 bytes
      00000020(37/4/20)          sub       esp,=32           ; Adjusted later if temporaries allocated
      00000026(38/4/20)       Label     __N3
   0010   if(allocated(x))then                                                                   AT 26
      00000026(39/5/30)          test      X,=-1

As a result of the failure to set the address of X, the allocation status of the allocatable variable is undefined if the entry SUBA is called. This is in violation of the Fortran 95 and later standards.

The warning (regarding X being used without being given an initial value) is, strictly speaking, incorrect.

The same kind of behavior also occurs when /64 is used.

25 May 2020 11:50 #25513

This bug has now been fixed for the next release of FTN95.

Please login to reply.