forums.silverfrost.com Forum Index forums.silverfrost.com
Welcome to the Silverfrost forums
 
 FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

Initializing an allocatable character array

 
Post new topic   Reply to topic    forums.silverfrost.com Forum Index -> Support
View previous topic :: View next topic  
Author Message
Ralf



Joined: 30 Aug 2007
Posts: 50
Location: munich

PostPosted: Mon Feb 13, 2023 7:44 pm    Post subject: Initializing an allocatable character array Reply with quote

With the new compiler version 8.95 I ran into problems with initializing character-arrays without specifying the array bounds.
See the following example:
Code:
      MODULE module_string_array
      character*10,allocatable,dimension(:)   :: list
      END MODULE module_string_array

      PROGRAM string_init
      use module_string_array

      call allocate_memory

      write(*,*)'before ',size(list)
      list = ' '
      write(*,*)'after ',size(list)
           
      stop
      end
     
      SUBROUTINE allocate_memory
      use module_string_array
      allocate(list(20),stat=ierr)
      return
      end     

The write statement before the initialization with blanks prints a size of 20, after the initialization it prints a size of 1.
If I increase the number of spaces (or other arbitrary characters) the size after the initialization equals the number of spaces (or characters).
E.g.:
Code:

      list = 'abcde'
 

leads to a size of 5.
This usually ends up in program crashes later on.
Back to top
View user's profile Send private message
JohnCampbell



Joined: 16 Feb 2006
Posts: 2554
Location: Sydney

PostPosted: Tue Feb 14, 2023 4:25 am    Post subject: Reply with quote

This result is not what I would expect either, when using /64

Code:
      MODULE module_string_array
      character*10,allocatable,dimension(:)   :: list
      real*8,allocatable,dimension(:)   :: array
      END MODULE module_string_array

      PROGRAM string_init
      use module_string_array
      use iso_fortran_env

      write (*,*) compiler_version()

      call allocate_memory

      write(*,*)'before use      ',size(list),size(array)
      list(:)  = ' '
      array(:) = 1
      write(*,*)'after list(:)   ',size(list),size(array)
      list     = ' '
      array    = 2
      write(*,*)'after list = " "',size(list),size(array)
      list     = [ ' ', ' ' ]
      array    = [ 2, 3, 4 ]
      write(*,*)'after list [ , ]',size(list),size(array)
           
      stop
      end
     
      SUBROUTINE allocate_memory
      use module_string_array
      integer :: ierr
      allocate(list(20),stat=ierr)
      allocate(array(20),stat=ierr)
      return
      end

This produced :
Code:
Program entered
 FTN95 v8.92
 before use                         20                   20
 after list(:)                       1                   20
 after list = " "                    1                   20
 after list [ , ]                    2                    3


allocatable real arrays look to perform as expected, but perhaps not character arrays ?

Does this mark a change in Fortran from F95 to F03 ?
It does worry me that my understanding of the F95 approach may be changed with auto allocate.

I am not sure how or when auto allocate should apply.
How can you confidently initialise an allocatable (character) array ?

Gfortran produces
Code:
 GCC version 11.1.0
 before use                20          20
 after list(:)             20          20
 after list = " "          20          20
 after list [ , ]           2           3


To date, I have not intentionally used auto allocate in an initialisation statement, but worry if my F95 usage may do this.
Back to top
View user's profile Send private message
mecej4



Joined: 31 Oct 2006
Posts: 1886

PostPosted: Tue Feb 14, 2023 5:30 am    Post subject: Reply with quote

Fortran 2003 and 2008 provided additional capabilities (deferred length character variables, reallocate-on-assignment) that are relevant to the topic of this thread. A brief summary is provided in a post by "Dr.Fortran", i.e., Steve Lionel, in the Intel Fortran forum:

https://community.intel.com/t5/Intel-Fortran-Compiler/Describe-assume-realloc-lhs/m-p/1255621

I took Ralf's example code and modified it to test some of these features. My modified code:
Code:
      MODULE module_string_array
      character(len=:), allocatable   :: list
      real*8,allocatable,dimension(:)   :: array
      END MODULE module_string_array

      PROGRAM string_init
      use module_string_array
      use iso_fortran_env

      write (*,*) compiler_version()

     ! call allocate_memory
      list = 'pq'
      array = [1.0,2.0,3.0]
      write(*,10)'before use      ',len(list),size(array)
      list  = ' '
      array(:) = 1
      write(*,10)'after list   ',len(list),size(array)
      list     = ' '
      array    = 2
      write(*,10)'after list = " "',len(list),size(array)
      list     = 'ab' // 'cde '
      array    = [ 2, 3, 4 ]
      write(*,10)'after array [ , ]',len(list),size(array)
   10 format(1x,A,T20,2i4)
      stop
      end


FTN95 8.95 compiles this code if /64 is provided. Otherwise (i.e., 32-bit target), the compiler crashes with an access violation. The output with /64:
Code:
 FTN95 v8.95
 before use           2   3
 after list           1   3
 after list = " "     1   3
 after array [ , ]    1   3


The output with Gfortran:
Code:
 GCC version 11.3.0
 before use           2   3
 after list           1   3
 after list = " "     1   3
 after array [ , ]    6   3
Back to top
View user's profile Send private message
JohnCampbell



Joined: 16 Feb 2006
Posts: 2554
Location: Sydney

PostPosted: Tue Feb 14, 2023 7:41 am    Post subject: Reply with quote

I generated some further tests for re-allocate for character and real arrays.
FTN95 appears to treat character arrays differently to real arrays and differently to Gfortran.
Code:
      MODULE module_string_array
      character*10,allocatable,dimension(:)   :: list
      real*8,allocatable,dimension(:)   :: array
      END MODULE module_string_array

      PROGRAM string_init
      use module_string_array
      use iso_fortran_env
      integer :: i
      integer, parameter :: n = 20

      write (*,*) compiler_version()

      call allocate_memory

      write(*,*)'before use      ',size(list),size(array)

!  Initialise the allocated array : no reallocation ?
      list     = ' '
      array    = 0
      write(*,*)'after initialise',size(list),size(array)    ! FTN95 gives incorrect character array size

!  Hopefully not change to SIZE ?
      list(:)  = ' '
      array(:) = 1
      write(*,*)'after list(:) = ',size(list),size(array)    ! FTN95 gives incorrect character array size

!  These should reallocate and change SIZE
      list     = [ ( ' ',    i=1,11 ) ]                      !  FTN95 works for this character array definition
      array    = [ (dble(i), i=1,size(array)) ]              !  FTN95 works for real array
      write(*,*)'after list = [ ]',size(list),size(array)    ! FTN95 gives correct size

!  This reallocate of list does not work with FTN95
!      list     = [ ( ' ',    i=1,size(array)) ]             !  FTN95 fails with intrinsic size, gfortran ok
!      n = 20 ! size(array)                                  !  FTN95 fails if n is a variable
      list     = [ ( ' ',    i=1,n )          ]              !  only works for n as parameter
      array    = [ (dble(i), i=1,size(array)) ]              !  size is ok for real array
      write(*,*)'after list = " "',size(list),size(array)    ! FTN95 now gives correct character array size

!  This definately should re-Allocate
      list     = [ ' ', ' ' ]
      array    = [ 2, 3, 4 ]
      write(*,*)'after list [ , ]',size(list),size(array)    ! FTN95 gives correct character array size
           
      stop
      end
     
      SUBROUTINE allocate_memory
      use module_string_array
      integer :: ierr
      allocate (list(20),stat=ierr)
      allocate (array(20),stat=ierr)
      return
      end

I am not sure if character fails all are valid Fortran, as I rarely actively use re-Allocate.

My biggest worry is if my old usage (especially initialisation) of allocatable arrays will now cause re-allocation.
Certainly, initialisation of (character) arrays, as in my first 2 cases, should not change SIZE ?

Can anyone clarify if "list = ' '" or "list(:) = ' '" should NOT lead to reallocation,
while "list = [ ' ', ' ' ]" should.
This arbitrary use of "list =" looks confusing to me !!
Back to top
View user's profile Send private message
JohnCampbell



Joined: 16 Feb 2006
Posts: 2554
Location: Sydney

PostPosted: Tue Feb 14, 2023 9:08 am    Post subject: Reply with quote

This is another example where re-allocation (F2003 implimented feature?) differs between FTN95 and Gfortran
FTN95 does not appear to apply re-allocation to xx in "xx = yy(1:7)"

Code:
   real, allocatable :: xx(:), yy(:)
   integer :: n, i

   n = 15
   allocate ( xx(n) )

   n = 25
   allocate ( yy(n) )

   xx = 3.14
!   yy = 2.3
   do i = 1,size(yy)
     yy(i) = 2.3 + 0.01*i
   end do
   
   write (*,*) 'xx',xx(1), xx(9), size(xx)
   write (*,*) 'yy',yy(1), yy(9), size(yy)

   xx(1:7) = yy(1:7)
   write (*,*) 'xx',xx(1), xx(9), size(xx)
   do i = 1,size(xx)
     write (*,*) i, xx(i), yy(i)
   end do

! This should re-allocate xx to size(xx) = 7,
!  FTN95 retains size(xx) = 15 and sets xx(1:15) = yy(1:15)

   write (*,*) ' '
   xx      = yy(1:7)
   n = size(xx)
   write (*,*) 'xx',xx(1), xx(n), size(xx), n
   do i = 1,size(xx)
     write (*,*) i, xx(i), yy(i)
   end do

   end


Line 29 " xx = yy(1:7)" appears to be implemented as
size(xx) remains as 15
xx(1:size(xx)) = yy(1:size(xx))

rather than
allocate ( xx(7) )
xx(1:7) = yy(1:7)

ie, size(xx) is not redefined

I note in an earlier example, the following reallocation worked.
array = [ 2, 3, 4 ]
Back to top
View user's profile Send private message
PaulLaidler
Site Admin


Joined: 21 Feb 2005
Posts: 7924
Location: Salford, UK

PostPosted: Wed Feb 15, 2023 7:23 am    Post subject: Reply with quote

I plan to look at these issues next week. I will also describe how FTN95 handles "allocate on assignment" so that users will be able to understand how this relates to existing code.
Back to top
View user's profile Send private message AIM Address
PaulLaidler
Site Admin


Joined: 21 Feb 2005
Posts: 7924
Location: Salford, UK

PostPosted: Sun Feb 19, 2023 10:07 am    Post subject: Reply with quote

The bug in FTN95 that is exposed by Ralf's code has been fixed for the next release of FTN95.

In the meantime here are 3 ways to make this code work when using the latest release.

1) FTN95 does not plant code for "allocate on assignment" when an explicit ALLOCATE for that variable appears beforehand (that is, as the subprogram is scanned from top to bottom). In Ralf's code the ALLOCATE is hidden in a subroutine so FTN95 does not see it and code for "allocate on assignment" is planted. The planted code is incorrect for an array of characters assigned to a scalar.

2) FTN95 implements 200x features when the command line option /F2K is applied. This is currently the default so /-F2K can be used to avoid all 200x features that are currently available.

3) The command line option "/INHIBIT_F2K 1" switches off "allocate on assignment". The value one is used for "allocate on assignment" and is currently the only value that is implemented.
Back to top
View user's profile Send private message AIM Address
PaulLaidler
Site Admin


Joined: 21 Feb 2005
Posts: 7924
Location: Salford, UK

PostPosted: Mon Feb 20, 2023 12:49 am    Post subject: Reply with quote

Two bugs, one for code presented above by mecej4 and one for John's code have been fixed for the next release of FTN95.

But with these fixes John's code using array sections will still not run (or will not run correctly) when using FTN95 because xx is explicitly allocated with the result that code for "allocate on assignment" is not planted.

The way that FTN95 works in the context of John's code is not standard conforming and probably needs addressing.

The problem is that standard conforming "allocate on assignment" has an impact on existing code that adds an unwelcome overhead... Either memory already explicitly allocated is immediately re-allocated or tests must be planted to check that re-allocation is not necessary.
Back to top
View user's profile Send private message AIM Address
PaulLaidler
Site Admin


Joined: 21 Feb 2005
Posts: 7924
Location: Salford, UK

PostPosted: Mon Feb 20, 2023 1:35 pm    Post subject: Reply with quote

As a final step in this thread, FTN95 has been amended so that it becomes Standard conforming in this context when /ISO is applied on the command line.

This means that, when /ISO is applied, code will be planted for "allocate on assignment" even when an explicit ALLOCATE for the given variable appears beforehand in the code.

In this way you could do an initial explicit ALLOCATE for a variable and still do an "allocate on assignment" later in the code for the same variable.
Back to top
View user's profile Send private message AIM Address
PaulLaidler
Site Admin


Joined: 21 Feb 2005
Posts: 7924
Location: Salford, UK

PostPosted: Mon Feb 20, 2023 5:48 pm    Post subject: Reply with quote

FTN95 v8.96 can now be downloaded from http://forums.silverfrost.com/viewtopic.php?t=4245.
Back to top
View user's profile Send private message AIM Address
Display posts from previous:   
Post new topic   Reply to topic    forums.silverfrost.com Forum Index -> Support All times are GMT + 1 Hour
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group