重温:Fortran 程序中的堆栈溢出

发布于 2024-07-24 08:04:57 字数 4254 浏览 4 评论 0原文

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

我很抱歉: 我花了一整天的时间编写代码,终于可以工作了。 然而,声明 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

I am getting stack overflow when executing the following code in Compac Fortran.
Specially for the line:

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

What I am doing is to read the NX,NY,DX,DY from a parameter file.

Any suggestions?

       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

NOTE: Changing from (NGMAX=30000) to (NGMAX=30) did not help.

Yes I have changed all the instances of NGMAX to 30.

The new version is listed below.


    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)

I am so sorry:
I worked on the code all the day and finally its working.
Howevere, declaring NX and NY, is what we do not need.
I want to to read these parameters from the parameter file.
The code is as follows:


      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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

往日情怀 2024-07-31 08:04:57

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

您可以做的是打印出从 linana.para 文件中读取的 NXNY 值,看看它们对您是否有意义应用。

It sounds like the subroutine ANALYSIS is allocating space on the stack based on the parameters passed into it (NX and NY). If those values are too large, then there may not be enough space on the stack to allocate the arrays.

What you can do is print out the values of NX and NY as read from the linana.para file to see whether they make sense for your application.

百变从容 2024-07-31 08:04:57

呵呵。 好吧,从技术上讲,这可能属于 ServerFault,因为这是操作系统问题,但我认为那里也没有人会回答 VMS 问题。 对于我和 VMS 来说已经有一段时间了,对于 FORTRAN 来说甚至更长,但我会尝试一下...

好吧,这就是您所得到的:ANALYSIS 子例程有 4 个数组,每个数组有 (30,000*100)=3,000,000 个单元格,每个单元格为 12M单元或每个 8 字节(我认为?) 为 72Mbytes。 再加上整数数组 IZ 和实数数组 VX、VY 和 VZ 占用的空间,我无法估计,因为我不知道 NX 和 NY 的最大值是多少。

无论如何,VAX 上至少有 144,000 个页面,Alpha 上至少有 24,000 个页面(加上其他 4 个阵列)。 您的进程地址表至少需要是该值的 2 倍(实际上要多一点),因为用户堆栈只能获得该值的一半。

因此,转到命令提示符并输入“SHOW PROC/MEM”并告诉我它的内容(我想我是对的)。

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

将数组设为全局可能行不通,因为堆和静态分配空间并不比堆栈大。

好的,我看到您的最大 NX、NY 值为 5,000。 这又是 4*25,000,000 或 100,000,000。 每个 8 字节即 800MB 加上上面的 72MB。 坏消息是,无论 VMS 进程设置如何,VAX 在架构上都限制为 1GB 的用户堆栈,因此我们希望浮点数为 4 字节(而不是 8 字节),或者您使用的是 Alpha。

Heh. Well, technically, this probably belongs on ServerFault because it's an OS problem, but I don't think that there's anyone over there who going to answer VMS questions over there either. IT been a while for me and VMS and even longer for FORTRAN, but Ill give it a go...

OK, here's what you've got: the ANALYSIS subroutine has 4 arrays with (30,000*100)=3,000,000 cells each that's 12M cells or 8 bytes each (I think?) for 72Mbytes. Add to that the space taken up by the integer array IZ and the real arrays VX, VY and VZ, which I cannot estimate because I do not know what the max values of NX and NY are.

Anyway, that's a minimum of 144,000 pages on a VAX or 24,000 pages for an Alpha (plus add to that the other 4 arrays). Your process address table needs to be at least 2x that (slighty more, actually), because the user stack only get's half of that.

So, go to the command prompt and type "SHOW PROC/MEM" and tell me what it says (I think I've got that right).

Note: NX, NY are just the parameters to the DIMENSION, it the arrays that are taking up the stack.

Making the arrays Global probably won't work because the heap and static allocation spaces aren't any larger than the stack.

OK, I see your max NX, NY values are 5,000. That's another 4*25,000,000 or 100,000,000. At 8 bytes each that's 800MB plus the 72MB above. The bad news is that the VAX is architecurally limited to a user stack of 1GB, regardless of the VMS Process settings, so let's hope either that the Floats are 4bytes (and not 8) or that you are on an Alpha.

一梦浮鱼 2024-07-31 08:04:57

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

请注意您分配的大小:

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)

您为四个数组 XLS中的每一个数组分配 30000 * 100 个值(我假设是实数)的空间XLE、YLSYLE。 那是 12,000,000 个值。 假设 32 位值,则内存为 48 MB。 但我依稀记得在某些平台上,实数是80位? 在这种情况下,内存将是 120 Meg。

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

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

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

Assuming the exception is happening on the line you mention, then your program's stack is insufficently large for the variables being allocated on it. You need to find the flag in your compiler to increase the default stack allocation on your program. Or, if you are not using recursion at all, you can make those variables global variables so they are not allocated on the stack.

Note the size you're allocating:

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)

You're allocating space for 30000 * 100 values (reals, I assume) for each of the four arrays XLS, XLE, YLS, and YLE. That's 12,000,000 values. Assuming 32-bit values, it's 48 Meg of memory. But I vaguely recall that on some platforms, reals are 80 bits? In that case it would be 120 Meg of memory.

Do you really need your arrays to be 30,000 elements long in one dimension? If not, reducing that allocation may help you.

Look at the compiler options for the FORTRAN compiler you're using. I remember that the VAX/VMS FORTRAN compiler had a command-line option to make all variables static, which is to say not allocated on the stack. Assuming you can guarantee that you will not do any recursion, this may be the quickest solution to your problem.

Another option you have is putting all of the large arrays into a COMMON block, but note that arrays in a common block cannot be dynamically sized.

你的他你的她 2024-07-31 08:04:57

看起来您的代码是 Fortran77 如果是的话,以下内容应该有意义,如果不是,它可能会给您一些线索。

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

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

例如 - 对于 NX=2456 & 纽约=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)

...
返回
我不记得

了,但可能可以在主程序中使用参数语句,以便您完全参数化上面的主程序。

It looks like your code is Fortran77 if so the following should make some sense if not it might give you some clues.

In Fortran77 there is no dynamic memory allocation support in the language standard, a number of compilers did have some support for it but by using compiler specific extensions. Your code does not trigger any memory of an extension looking like that.

One way of doing what you wanted would be to generate a main program which would declare the array space and then pass the arrays as parameters to subroutines. This main program would be compiled and linked with the rest of the code. Each set of values would produce a new main program.

For example - for 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)

...
RETURN
END

I cannot remember but it may have been possible to use the parameter statement in the main program so you fully parameterize the main program above.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文