问题
In relation to a recent post regarding how to declare the array shape concisely, I tried the following three patterns, i.e., (A) automatic re-allocation, (B) sourced allocation, and (C) allocation with assumed shape. Then gfortran seems to give incorrect results for b(:,:)
in the case of sourced allocation. Here, am I doing something wrong, or is this simply because it is not yet fully supported by gfortran? Although the latter seems likely, I am not very sure if my installation or usage of gcc5 and 6 is correct (I am using Linux x86_64).
program main
implicit none
integer, parameter :: p=3, q=4, r=5
integer a( p, q, r ), i, j, k
integer, allocatable :: b( :, : )
a = reshape( [ ((( 100*i + 10*j + k, i=1,p), j=1,q), k=1,r) ], [p,q,r] )
print *
print *, "shape( a ) = ", shape( a )
print *, "a(:,:,:) = ", a
print *, "a(:,1,:) = ", a(:,1,:)
b = a( :, 1, : ) !! (A) automatic (re)allocation
! allocate( b, source = a( :, 1, : ) ) !! (B) sourced allocation
! allocate( b, mold = a( :, 1, : ) ) !! (C) allocation with assumed shape
print *
print *, "shape( b ) = ", shape( b )
print *, "b(:,:) = ", b
end
Results: (In all cases, automatic reallocation gives the correct result.)
gfortran4.8.2
[A]
shape( b ) = 3 5
b(:,:) = 111 211 311 112 212 312 113 213 313 114 214 314 115 215 315
[B], [C]
f951: internal compiler error: Segmentation fault
gfortran5.2.1
[A]
shape( b ) = 3 5
b(:,:) = 111 211 311 112 212 312 113 213 313 114 214 314 115 215 315
[B], [C]
allocate( b, source = a( :, 1, : ) )
1
Error: Array specification required in ALLOCATE statement at (1)
gfortran6.0.0 (experimental)
[A]
shape( b ) = 3 5
b(:,:) = 111 211 311 112 212 312 113 213 313 114 214 314 115 215 315
[B] <--- seems incorrect
shape( b ) = 3 5
b(:,:) = 0 -1094645928 57 141 241 341 142 242 342 143 243 343 144 244 344
[C]
shape( b ) = 3 5
b(:,:) = (garbage data, reasonable)
Intel Fortran 14.0.1 (-assume realloc_lhs)
[A]
shape( b ) = 3 5
b(:,:) = 111 211 311 112 212 312 113 213 313 114 214 314 115 215 315
[B]
shape( b ) = 3 5
b(:,:) = 111 211 311 112 212 312 113 213 313 114 214 314 115 215 315
[C]
shape( b ) = 3 5
b(:,:) = 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
Oracle Fortran 12.4
[A]
shape( b ) = 3 5
b(:,:) = 111 211 311 112 212 312 113 213 313 114 214 314 115 215 315
[B]
shape( b ) = 3 5
b(:,:) = 111 211 311 112 212 312 113 213 313 114 214 314 115 215 315
[C]
shape( b ) = 3 5
b(:,:) = (garbage data, reasonable)
回答1:
Sourced allocation was introduced in Fortran 2003 and the rules/constraints were changed in Fortran 2008. Rejection of the program by gfortran 5.2.1 would appear to be a consequence of following F2003.
Under F2003 sourced allocation required the explicit specification of array bounds for the array to be allocated. Under F2008 this is not required, and additionally multiple objects to be allocated could be specified. So, your code isn't valid F2003.
The program (well, that allocation part) is, though, valid F2008: the bounds of the array to be allocated may come from the source expression just as the value does. The contiguity or otherwise of the array section shouldn't be important as it's the value (and bounds) of the expression being key. Naturally, the calculation of bounds of the expression array offers opportunity for things to go wrong.
In conclusion, the allocation statement is valid under F2008 but not under F2003. A compiler which is using the F2003 rules must be able to detect the violation rather than being free to give nonsense. But F2008 is easy enough to do buggily.
And, thanks to your testing, the safe way to write this code for gfortran would be
allocate(b(p,r), source=a(:,1,:))
Indeed, documentation for gfortran lists the giving of bounds as being "unimplemented".
来源:https://stackoverflow.com/questions/34384145/sourced-allocation-of-a-non-contiguous-array-section