Fortran77 过程中输出数组维数的减少

Reduction of output array dimension in Fortran77 procedure

我正在编写大型 Fortran 代码,其中部分代码是用 FORTRAN77 编写的。 有一段代码,导致调试器引发如下错误:

Fortran runtime error: 
Index '2' of dimension 1 of array 'trigs' above upper bound of 1

但是在没有调试选项的情况下编译时运行并且不会使程序崩溃。使用的调试选项:

-g -ggdb -w -fstack-check -fbounds-check\
     -fdec  -fmem-report -fstack-usage

有问题的代码的逻辑如下:在文件variables.cmn中我声明

implicit none

integer factors,n
real*8 triggers
parameter (n=32)

common /fft/ factors(19), triggers(6*n)

变量 factorstriggers 在过程 initialize:

中初始化
include 'variables.cmn'
...
CALL FFTFAX(n,factors,triggers)
...

FFTFAX 在另一个过程中声明为:

SUBROUTINE FFTFAX(N,IFAX,TRIGS)
implicit real*8(a-h,o-z)
DIMENSION IFAX(13),TRIGS(1)

    CALL FAX (IFAX, N, 3)
    CALL FFTRIG (TRIGS, N, 3)

RETURN
END

让我们看看程序 FFTRIG:

  SUBROUTINE FFTRIG(TRIGS,N,MODE)
  implicit real*8(a-h,o-z)
  DIMENSION TRIGS(1)

        PI=2.0d0*ASIN(1.0d0)
        NN=N/2
        DEL=(PI+PI)/dFLOAT(NN)
        L=NN+NN

        DO 10 I=1,L,2
        ANGLE=0.5*FLOAT(I-1)*DEL
        TRIGS(I)=COS(ANGLE)
        TRIGS(I+1)=SIN(ANGLE)
10 CONTINUE
        DEL=0.5*DEL
        NH=(NN+1)/2
        L=NH+NH
        LA=NN+NN

        DO 20 I=1,L,2
        ANGLE=0.5*FLOAT(I-1)*DEL
        TRIGS(LA+I)=COS(ANGLE)
        TRIGS(LA+I+1)=SIN(ANGLE)
20 CONTINUE

FFTFAXFFTRIG 过程中,参数维度的界限与实际输入数组大小不同(对于 TRIGS,分别为 1 和 19)。 我在无调试器编译设置中调用 FFTFAX 后打印出 TRIGS

 trigs:                    1.0000000000000000        0.0000000000000000\
  0.99144486137381038       0.13052619222005157       0.96592582628906831\
  0.25881904510252074       0.92387953251128674       0.38268343236508978\
  ...

我的问题是:

  1. 是符号: 维度触发器(1) 不仅仅是设置数组的界限?
  2. 为什么程序甚至可以在无调试器模式下运行?
  3. 正在设置: 维度触发器(*) 如果我希望变量触发是程序的结果,这是一个很好的解决方案吗?

在 f77 语句中,如 DIMENSION TRIGS(1) 或类似的或 ..(*) 与任何数字,如果涉及过程的参数,则只告诉编译器 数组的秩,内存中的长度必须分配给子程序调用中给出的数组,通常 f77 不检查这个! 我的建议是使用 (*) 或更好地重新格式化(如有必要)将 f77 源代码格式化为 f90(显示的位将编译而无需更改...)。 并在 subroutines/procedures 的声明中使用使用 n 计算的维度。 Fortan 通过地址传递参数(即子例程中的 trigs(i) 只是 将引用内存位置,对应于 trigs(1) + i*size(real*8).

的地址

编写子例程代码的更一致的方法可能是:

SUBROUTINE FFTRIG(TRIGS,N,MODE)
!   implicit real*8(a-h,o-z)
integer, intent(in) :: n      
real(kind=8)        :: trigs(6*n)
integer             :: mode
!  DIMENSION TRIGS(1)
.....
    PI=2.0d0*ASIN(1.0d0)
.....

或编译器检查能力较差

SUBROUTINE FFTRIG(TRIGS,N,MODE)
!   implicit real*8(a-h,o-z)
integer, intent(in) :: n      
real(kind=8)        :: trigs(:)
integer             :: mode
!  DIMENSION TRIGS(1)
.....
    PI=2.0d0*ASIN(1.0d0)
.....

为了回答您的问题,我会将 TRIGS(1) 更改为 TRIGS(*),只是为了更清楚地识别数组 TRIGS,因为它没有提供维度。 TRIGS(1) 是 F77 之前的遗留物,用于确定如何识别它。

使用 TRIGS(:) 是不正确的,因为以这种方式定义数组 TRIGS 需要调用 FFTRIG 的任何例程都具有 INTERFACE 定义。此更改会导致其他错误。

您的问题是将调试器对数组大小的需求与不包括提供的大小的语法混合在一起。为了克服这个问题,您可以将数组 TRIGS 的声明维度作为额外声明的参数传递给调试器进行检查。使用 "debugger" 模式时,某些编译器会提供隐藏属性,包括所有数组的声明大小。