简体   繁体   English

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

[英]Reduction of output array dimension in Fortran77 procedure

I am working on a large Fortran code, where parts are written in FORTRAN77. 我正在处理一个大型的Fortran代码,其中的部分是用FORTRAN77编写的。 There is a piece of code, which causes debugger to raise errors like: 有一段代码,导致调试器引发如下错误:

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

but when compiled without debugging options runs and does not crash the program. 但是,如果在不使用调试选项进行编译的情况下运行,则不会使程序崩溃。 Debugging options used: 使用的调试选项:

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

The logic of the problematic piece of code is following: in file variables.cmn I declare 有问题的代码的逻辑如下:在文件variables.cmn我声明

implicit none

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

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

Variables factors and triggers are initialized in procedure initialize : 变量factorstriggers在过程initialize

include 'variables.cmn'
...
CALL FFTFAX(n,factors,triggers)
...

FFTFAX is declared in another procedure as: 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

and lets look at procedure FFTRIG : 让我们看一下程序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

In both FFTFAX and FFTRIG procedures there are different bounds for dimensions of arguments than the actual input array size (for TRIGS it is 1 and 19, respectively). FFTFAXFFTRIG过程中,参数的大小与实际输入数组大小的边界不同(对于TRIGS ,分别为1和19)。 I printed out TRIGS after calling FFTFAX in no-debugger compilation setup: 我打印出来TRIGS调用后FFTFAX在无调试编译设置:

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

My questions are: 我的问题是:

  1. Is notation : DIMENSION TRIGS(1) something more than setting bound of an array? 表示法:DIMENSION TRIGS(1)不仅仅是设置数组的界限吗?
  2. Why is the program even working in no-debugger mode? 为什么该程序甚至可以在无调试器模式下运行?
  3. Is setting: DIMENSION TRIGS(*) a good fix if I want variable trigs be a result of the procedure? 如果我希望变量触发是该过程的结果,则是否设置:DIMENSION TRIGS(*)是一个很好的解决方法?

In f77 statements like the DIMENSION TRIGS(1) or similar or ..(*) with any number, if pertaining an argument of the procedure just tells the compiler the rank of the array, the length in memory must be assigned to the array which is given in the call of the subroutine, normally f77 does not check this! 在f77语句中,例如DIMENSION TRIGS(1)或类似或带有任何数字的..(*),如果与该过程的参数有关,则仅告诉编译器数组的等级,必须将内存中的长度分配给该数组在子程序的调用中给出,通常f77不检查! My recommendation either use (*) or better reformat (if necessary) the f77 sources to f90 (the bits shown would compile without change...). 我的建议是使用(*)或将格式更好的格式(如有必要)重新格式化为f90到f90(显示的位将进行编译而不会发生变化...)。 and use dimension computed using n in the declaration within the subroutines/procedures. 并使用在子例程/过程的声明中使用n计算的维。 Fortan passes arguments by address (ie trigs(i) in the subroutine just will refer on the memory location, which corresponds to the address of trigs(1) + i*size(real*8). Fortan通过地址传递参数(例如,子例程中的trigs(i)只会引用内存位置,该位置对应于trigs(1)+ i * size(real * 8)的地址)。

A more consisted way to write the subroutine code could be: 编写子例程代码的更通用的方法可能是:

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)
.....

or with less ability for the compiler to check 或编译器检查的能力较低

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)
.....

To answer your question, I would change TRIGS(1) to TRIGS(*), only to more clearly identify array TRIGS as not having it's dimension provided. 为了回答您的问题,我将TRIGS(1)更改为TRIGS(*),只是为了更清楚地标识数组TRIGS为未提供尺寸。 TRIGS(1) is a carry over from pre F77 for how to identify this. TRIGS(1)是F77之前版本的遗留物,用于识别此内容。

Using TRIGS(:) is incorrect, as defining array TRIGS in this way requires any routine calling FFTRIG to have an INTERFACE definition. 使用TRIGS(:)是不正确的,因为以这种方式定义数组TRIGS要求任何调用FFTRIG的例程都具有INTERFACE定义。 This change would lead to other errors. 此更改将导致其他错误。

Your question is mixing the debugger's need for the array size vs the syntax excluding the size being provided. 您的问题是将调试器对数组大小的需求与语法(不包括所提供的大小)混合在一起。 To overcome this you could pass the array TRIGS's declared dimension, as an extra declared argument, for the debugger to check. 为了克服这个问题,您可以将数组TRIGS的声明维作为额外的声明参数传递给调试器进行检查。 When using "debugger" mode, some compilers do provide hidden properties including the declared size of all arrays. 使用“调试器”模式时,某些编译器确实提供了隐藏的属性,包括所有数组的声明大小。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM