重访:Fortran程序中的Stack Overflow

时间:2009-06-20 01:54:27

标签: fortran stack-overflow

在Compac Fortran中执行以下代码时,我发现堆栈溢出。 特别为该行:

DIMENSION IZ(NX,NY),VX(NX-1,NY-1),VY(NX-1,NY-1),VZ(NX-1,NY-1)

我正在做的是从参数文件中读取NX,NY,DX,DY。

有什么建议吗?

       PARAMETER(NGMAX=30000)
       INTEGER NX,NY,DX,DY
       OPEN(6,FILE='MGSTAOriggroup15.asc',STATUS='old')
       OPEN(7,FILE='Gravity.asc',STATUS='old')
       OPEN(8,FILE='Gravity200.nor',STATUS='old')
       OPEN(9,FILE='linana.para',STATUS='old')
       OPEN(10,FILE='MGSTAOriggroup15coord.dat',STATUS='unknown')
       OPEN(12,FILE='MGSTAOriggroup15ncoord.dat',STATUS='unknown')
       OPEN(11,FILE='linana.fsn',STATUS='unknown')
       READ(9,*) NX,NY,DX,DY
       CALL ANALYSIS(NX,NY)
       Close(6)
       Close(7)
       Close(8)
       Close(9)
       Close(10)
       Close(11)
       Close(12)
C
       STOP 
     END
C 
      SUBROUTINE ANALYSIS(NX,NY)
      INTEGER NX,NY,DX,DY
      COMMON/COM1/ DX,DY
      PARAMETER(NGMAX=30000)
      DIMENSION KO(NGMAX)
      DIMENSION XLS(NGMAX,100),XLE(NGMAX,100),
     &          YLS(NGMAX,100),YLE(NGMAX,100)
      DIMENSION IZ(NX,NY),VX(NX-1,NY-1),VY(NX-1,NY-1),VZ(NX-1,NY-1)
      """"""""""""""""""""""""""""""""""""""""""""
      To the end

注意:从(NGMAX=30000)更改为(NGMAX=30)无效。

是的,我已将NGMAX的所有实例更改为30。

新版本如下所示。


    INTEGER NX,NY,DX,DY
    PARAMETER(NGMAX=30)
      COMMON /CM1/ FX(NGMAX),FY(NGMAX),FZ(NGMAX),FR(NGMAX),IL(NGMAX)
      COMMON /CM2/ JST(NGMAX),KST(NGMAX),JDP(NGMAX),KDP(NGMAX)
      COMMON /CM3/ XC(NGMAX),YC(NGMAX),ZC(NGMAX),KTYP(NGMAX)
      COMMON /CM4/ A(4,4),B(4),U(4)
    COMMON /CM5/ KO(NGMAX)
      COMMON /CM6/ XLS(NGMAX,10),XLE(NGMAX,10),
     &          YLS(NGMAX,10),YLE(NGMAX,10)
      OPEN(6,FILE='MGSTAOriggroup15.asc',STATUS='old')
      OPEN(7,FILE='Gravity.asc',STATUS='old')
      OPEN(8,FILE='Gravity200.nor',STATUS='old')
      OPEN(9,FILE='linana.para',STATUS='old')
      OPEN(10,FILE='MGSTAOriggroup15coord.dat',STATUS='unknown')
      OPEN(12,FILE='MGSTAOriggroup15ncoord.dat',STATUS='unknown')
      OPEN(11,FILE='linana.fsn',STATUS='unknown')
      READ(9,*) NX,NY,DX,DY
    CALL ANALYSIS(NX,NY)
      Close(6)
      Close(7)
      Close(8)
      Close(9)
      Close(10)
      Close(11)
      Close(12)
C
       STOP 
     END
C 
      SUBROUTINE ANALYSIS(NX,NY)
    INTEGER NX,NY,DX,DY
      COMMON/COM1/ DX,DY
    PARAMETER(NGMAX=30)
      COMMON /CM1/ FX(NGMAX),FY(NGMAX),FZ(NGMAX),FR(NGMAX),IL(NGMAX)
      COMMON /CM2/ JST(NGMAX),KST(NGMAX),JDP(NGMAX),KDP(NGMAX)
      COMMON /CM3/ XC(NGMAX),YC(NGMAX),ZC(NGMAX),KTYP(NGMAX)
      COMMON /CM4/ A(4,4),B(4),U(4)
    COMMON /CM5/ KO(NGMAX)
      COMMON /CM6/ XLS(NGMAX,10),XLE(NGMAX,10),
     &          YLS(NGMAX,10),YLE(NGMAX,10)
      DIMENSION IZ(NX,NY),VX(NX-1,NY-1),VY(NX-1,NY-1),VZ(NX-1,NY-1)

我很抱歉: 我整天都在处理代码,最后还在工作。 Howevere,宣布NX和NY,是我们不需要的。 我想从参数文件中读取这些参数。 代码如下:


      PARAMETER(NX=322,NY=399,NGMAX=30000)
C I need to change NX and NY to read from the parameter file
      CHARACTER infile1*80,infile2*80,infile3*80,outfile1*80
     &,outfile2*80,outfile3*80
      DIMENSION KO(NGMAX)
      DIMENSION XLS(NGMAX,100),XLE(NGMAX,100),
     &          YLS(NGMAX,100),YLE(NGMAX,100)
      DIMENSION IZ(NX,NY),VX(NX-1,NY-1),VY(NX-1,NY-1),VZ(NX-1,NY-1)
      DIMENSION FX(NGMAX),FY(NGMAX),FZ(NGMAX),FR(NGMAX),IL(NGMAX)
      DIMENSION JST(NGMAX),KST(NGMAX),JDP(NGMAX),KDP(NGMAX)
      DIMENSION XC(NGMAX),YC(NGMAX),ZC(NGMAX),KTYP(NGMAX)
      DIMENSION A(4,4),B(4),U(4)
C
    CALL getenv('INFILE1',infile1)
    CALL getenv('INFILE2',infile2)
    CALL getenv('INFILE3',infile3)
    CALL getenv('OUTFILE1',outfile1)
    CALL getenv('OUTFILE2',outfile2)
    CALL getenv('OUTFILE3',outfile3)
    OPEN(1,FILE='Alaa1.para',STATUS='old')
    READ(1,*)DX,DY,infile1,infile2,infile3,outfile1,outfile2
     &,outfile3
C
       OPEN(6,FILE=infile1,STATUS='old')
       OPEN(7,FILE=infile2,STATUS='old')
       OPEN(8,FILE=infile3,STATUS='old')
       OPEN(10,FILE=outfile1,STATUS='unknown')
       OPEN(12,FILE=outfile2,STATUS='unknown')
       OPEN(11,FILE=outfile3,STATUS='unknown')

       TO THE END

4 个答案:

答案 0 :(得分:1)

听起来子程序ANALYSIS正在根据传递给它的参数(NXNY)在堆栈上分配空间。如果这些值太大,那么堆栈上可能没有足够的空间来分配数组。

您可以执行的操作是打印出从NX文件中读取的NYlinana.para的值,看看它们是否对您的应用程序有意义。

答案 1 :(得分:0)

假设您提到的行发生了异常,那么您的程序堆栈对于在其上分配的变量来说是非常大的。您需要在编译器中找到标志以增加程序的默认堆栈分配。或者,如果您根本不使用递归,则可以将这些变量设为全局变量,以便它们不会在堆栈中分配。

请注意您分配的尺寸:

PARAMETER(NGMAX=30000)
DIMENSION KO(NGMAX)
DIMENSION XLS(NGMAX,100),XLE(NGMAX,100),YLS(NGMAX,100),YLE(NGMAX,100)
DIMENSION IZ(NX,NY),VX(NX-1,NY-1),VY(NX-1,NY-1),VZ(NX-1,NY-1)

您为四个数组realXLSXLE和{中的每一个都分配了30000 * 100个值(YLS s,我假设)的空间{1}}。这是12,000,000个值。假设32位值,它的内存为48兆。但我依旧回忆起在某些平台上,实时是80位?在那种情况下,它将是120兆的内存。

真的需要你的数组在一个维度上长达30,000个元素吗?如果没有,减少分配可能会对您有所帮助。

查看您正在使用的FORTRAN编译器的编译器选项。我记得VAX / VMS FORTRAN编译器有一个命令行选项,可以将所有变量设置为静态,也就是说不在堆栈上分配。假设您可以保证不会进行任何递归,这可能是解决问题的最快方法。

另一个选择是将所有大型数组放入COMMON块,但请注意,公共块中的数组不能动态调整大小。

答案 2 :(得分:0)

嘿。嗯,从技术上讲,这可能属于ServerFault,因为它是一个操作系统问题,但我不认为那边有人会在那里回答VMS问题。对我和VMS来说,它已经有一段时间了,对于FORTRAN来说甚至更长一段时间,但我会试一试......

好的,这就是你所拥有的:ANALYSIS子程序有4个阵列,其中(30,000 * 100)= 3,000,000个单元,每个单元为12M单元,或者每个8字节(我认为?)为72M字节。再加上整数数组IZ和真实数组VX,VY和VZ占用的空间,我无法估计,因为我不知道NX和NY的最大值是什么。

无论如何,这在VAX上至少有144,000页,对于Alpha来说是24,000页(加上其他4个数组)。您的进程地址表必须至少为2倍(实际上稍微多一点),因为用户堆栈只能获得其中的一半。

所以,转到命令提示符并输入“SHOW PROC / MEM”并告诉我它的内容(我认为我已经做到了)。

注意:NX,NY只是DIMENSION的参数,它是占用堆栈的数组。

使数组Global可能无法工作,因为堆和静态分配空间不大于堆栈。

好的,我看到你的最大NX,NY值是5,000。这是另一个4 * 25,000,000或100,000,000。每个8字节,800MB加上72MB以上。坏消息是VAX的架构限制为1GB的用户堆栈,无论VMS进程设置如何,所以我们希望Floats是4bytes(而不是8)或者你是Alpha。

答案 3 :(得分:0)

看起来您的代码是Fortran77,如果是这样,以下内容应该有所帮助,如果不是它可能会给你一些线索。

在Fortran77中,语言标准中没有动态内存分配支持,许多编译器确实对它有一些支持,但是使用了特定于编译器的扩展。您的代码不会触发任何类似的扩展内存。

执行所需操作的一种方法是生成一个主程序,该程序将声明数组空间,然后将数组作为参数传递给子程序。该主程序将被编译并与其余代码链接。每组值都会产生一个新的主程序。

例如 - 对于NX = 2456& NY = 789

  PROGRAM MAIN
  INTEGER NX, NY
  DIMENSION IZ(2456,789),VX(2455,788),VY(2455,788),VZ(2455,788)
  NX=2456
  NY=789
  CALL ANALYSIS(NX,NY,IZ,VX,VY,VZ)
  STOP
  END

  SUBROUTINE ANALYSIS(NX,NY,IZ,VX,VY,VZ)
  INTEGER NX,NY,DX,DY
  DIMENSION IZ(NX,NY),VX(NX-1,NY-1),VY(NX-1,NY-1),VZ(NX-1,NY-1)

...       返回       END

我记不清了但是可能在主程序中使用参数语句,因此您可以完全参数化上面的主程序。