|
forums.silverfrost.com Welcome to the Silverfrost forums
|
View previous topic :: View next topic |
Author |
Message |
Ralf
Joined: 30 Aug 2007 Posts: 50 Location: munich
|
Posted: Mon Feb 13, 2023 7:44 pm Post subject: Initializing an allocatable character array |
|
|
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.:
leads to a size of 5.
This usually ends up in program crashes later on. |
|
Back to top |
|
|
JohnCampbell
Joined: 16 Feb 2006 Posts: 2580 Location: Sydney
|
Posted: Tue Feb 14, 2023 4:25 am Post subject: |
|
|
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 |
|
|
mecej4
Joined: 31 Oct 2006 Posts: 1896
|
Posted: Tue Feb 14, 2023 5:30 am Post subject: |
|
|
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 |
|
|
JohnCampbell
Joined: 16 Feb 2006 Posts: 2580 Location: Sydney
|
Posted: Tue Feb 14, 2023 7:41 am Post subject: |
|
|
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 |
|
|
JohnCampbell
Joined: 16 Feb 2006 Posts: 2580 Location: Sydney
|
Posted: Tue Feb 14, 2023 9:08 am Post subject: |
|
|
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 |
|
|
PaulLaidler Site Admin
Joined: 21 Feb 2005 Posts: 8011 Location: Salford, UK
|
Posted: Wed Feb 15, 2023 7:23 am Post subject: |
|
|
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 |
|
|
PaulLaidler Site Admin
Joined: 21 Feb 2005 Posts: 8011 Location: Salford, UK
|
Posted: Sun Feb 19, 2023 10:07 am Post subject: |
|
|
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 |
|
|
PaulLaidler Site Admin
Joined: 21 Feb 2005 Posts: 8011 Location: Salford, UK
|
Posted: Mon Feb 20, 2023 12:49 am Post subject: |
|
|
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 |
|
|
PaulLaidler Site Admin
Joined: 21 Feb 2005 Posts: 8011 Location: Salford, UK
|
Posted: Mon Feb 20, 2023 1:35 pm Post subject: |
|
|
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 |
|
|
PaulLaidler Site Admin
Joined: 21 Feb 2005 Posts: 8011 Location: Salford, UK
|
|
Back to top |
|
|
|
|
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
|