首页 > 解决方案 > 减少 Fortran77 过程中的输出数组维数

问题描述

我正在编写一个大型 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)。TRIGS我在调用FFTFAX无调试器编译设置后打印出来:

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

我的问题是:

  1. 符号:DIMENSION TRIGS(1) 不仅仅是设置数组的界限吗?
  2. 为什么程序甚至在无调试器模式下工作?
  3. 如果我希望变量 trigs 是过程的结果,设置:DIMENSION TRIGS(*) 是否是一个很好的解决方法?

标签: debuggingfortrangfortrandimensionfortran77

解决方案


在 f77 语句中,如 DIMENSION TRIGS(1) 或类似的或具有任意数字的 ..(*),如果与过程的参数有关只是告诉编译器数组的等级,则内存中的长度必须分配给数组在子程序的调用中给出,通常 f77 不检查这个!我的建议是使用 (*) 或更好地将 f77 源重新格式化(如有必要)为 f90(显示的位将无需更改即可编译...)。并在子例程/过程中的声明中使用使用 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)
.....

推荐阅读