Fortran 程序中的堆栈溢出 [英] Stack Overflow in Fortran program
问题描述
我的简单 Fortran 程序有问题.我在 Fortran 77 中工作,使用 Compaq Visual Fortran.程序结构必须是主程序和子程序的形式,因为它是与有限元法相关的大程序的一部分.
I have a problem with my simple Fortran program. I am working in Fortran 77, using Compaq Visual Fortran. The program structure must be in the form of a main and a subroutine, because it is part of a big program related to the finite element method.
我的问题是我想设置值 10000 &NHELE
和 NVELE
分别为 10000,但是当我运行代码时,程序停止并给出以下错误:
My issue is that I would like to set the values 10000 & 10000 for NHELE
and NVELE
respectively, but when I run the code, the program stops and gives the following error:
forrt1: server <170>: program Exception - stack overflow
我尝试反复减少所需的值,直到达到 507 &507.此时代码运行无误.
I've tried iteratively reducing the required values, until I reached 507 & 507. At this point the code runs without errors.
但是,将值增加到 508 &508 导致同样的错误再次出现.
However, increasing the values to 508 & 508 causes the same error to reappear.
我认为问题与子程序NIGTEE
有关,因为当我在没有它的情况下重新排列程序时,一切正常.
I think the problem is related to the subroutine NIGTEE
, because when I rearrange the program without it, everything works fine.
我尝试通过使用菜单 project>>>settings>>link>>output>>reserve & 将堆栈大小增加到最大值提交
但这并没有什么不同.
I've tried increasing the stack size to a maximum by using the menu project>>settings>>link>>output>>reserve & commit
but this didn't make a difference.
我该如何解决这个问题?
How can I solve this problem?
这是我的程序:
PARAMETER(NHELE=508,NVELE=508)
PARAMETER(NHNODE=NHELE+1,NVNODE=NVELE+1)
PARAMETER(NTOTALELE=NHELE*NVELE)
DIMENSION MELE(NTOTALELE,4)
CALL NIGTEE(NHELE,NVELE,NHNODE,NVNODE,NTOTALELE,MELE)
OPEN(UNIT=7,FILE='MeshNO For Rectangular.TXT',STATUS='UNKNOWN')
WRITE(7,500) ((MELE(I,J),J=1,4),I=1,NTOTALELE)
500 FORMAT(4I20)
STOP
END
SUBROUTINE NIGTEE(NHELE,NVELE,NHNODE,NVNODE,NTOTALELE,MELE)
DIMENSION NM(NVNODE,NHNODE),NODE(4)
DIMENSION MELE(NTOTALELE,4)
KK=0
DO 20 I=1,NVNODE
DO 20 J=1,NHNODE
KK=KK+1
NM(I,J)=KK
20 CONTINUE
KK=0
DO 30 I=1,NVELE
DO 30 J=1,NHELE
NODE(1)=NM(I,J)
NODE(2)=NM(I,J+1)
NODE(3)=NM(I+1,J+1)
NODE(4)=NM(I+1,J)
KK=KK+1
DO 50 II=1,4
50 MELE(KK,II)=NODE(II)
30 CONTINUE
RETURN
END
谢谢.
推荐答案
更新:
这是您的实际问题.您的 NM
数组被声明为由 NVNODE
行组成的 NHNODE
单元的二维数组.如果是 10,000 x 10,000,那么除了程序使用的任何其他内存之外,您将需要超过 381 MB 的内存来单独分配这个数组.(相比之下,如果数组是 500 x 500,则同一个数组只需要大约 1 兆字节的内存.)
Here's your actual problem. Your NM
array is being declared as being a two-dimensional array of NHNODE
cells by NVNODE
rows. If that is 10,000 by 10,000, then you will need more than 381 megabytes of memory to allocate this array alone, aside from any other memory being used by your program. (By contrast, if the array is 500 by 500, you only need about 1 megabyte of memory for the same array.)
问题是旧的 Fortran 会直接在代码段或堆栈中分配所有数组.操作系统堆"(大型对象的通用内存)的概念是在 1977 年发明的,但 Fortran 77 仍然没有任何构造来使用它.因此,每次调用您的子程序时,它都必须将堆栈指针压入堆栈,以便为堆栈上的 381 兆字节空间腾出空间.这几乎肯定大于您的操作系统允许堆栈段的空间量,并且您正在溢出堆栈内存(因此得到 堆栈溢出).
The problem is that old Fortran would allocate all the arrays directly in the code segment or on the stack. The concept of an OS "heap" (general purpose memory for large objects) had been invented by 1977, but Fortran 77 still didn't have any constructs for making use of it. So every time your subroutine is called, it has to push the stack pointer to make room for 381 megabytes of space on the stack. This is almost certainly larger than the amount of space your operating system is allowing for the stack segment, and you are overflowing stack memory (and hence getting a stack overflow).
解决方案是从不同的地方分配内存.我知道在旧的 Fortran 中,可以使用 COMMON
块直接从您的代码段静态分配内存.您仍然不能动态分配更多,因此您的子例程不能重入,但如果您的子例程一次只被调用一次(看起来是这样),这可能是最好的解决方案.
The solution is to allocate that memory from a different place. I know in old Fortran it is possible to use COMMON
blocks to statically allocate memory directly from your code segment. You still can't dynamically allocate more, so your subroutine can't be reentrant, but if your subroutine only gets called once at a time (which it appears to be) this may be the best solution.
更好的解决方案是切换到 Fortran 90 或更新版本并使用 ALLOCATE
关键字在堆而不是堆栈上动态分配数组.然后,您可以分配尽可能大的块,因为您的操作系统可以给您,但您不必担心堆栈溢出,因为内存将来自另一个地方.
A better solution would be to switch to Fortran 90 or newer and use the ALLOCATE
keyword to dynamically allocate the arrays on the heap instead of the stack. Then you can allocate as large a chunk as your OS can give you, but you won't have to worry about overflowing the stack, since the memory will be coming from another place.
您可以通过在编译器中更改它来解决此问题,例如 M.S.B.建议,但更好的解决方案是简单地修复代码.
You may be able to fix this by changing it in the compiler, as M.S.B. suggests, but a better solution is to simply fix the code.
这篇关于Fortran 程序中的堆栈溢出的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!