Fortran程序中的堆栈溢出 [英] Stack Overflow in Fortran program

查看:541
本文介绍了Fortran程序中的堆栈溢出的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的简单Fortran程序有问题。我在使用Compaq Visual Fortran的Fortran 77中工作。程序结构必须是主程序和子程序的形式,因为它是与有限元方法有关的大程序的一部分。



我的问题是我想要设置值10000& 10000分别为 NHELE NVELE ,但是当我运行代码时,程序停止并出现以下错误:

  forrt1:server< 170> ;:程序异常 - 堆栈溢出

我试着迭代地减少所需的值,直到达到507& 507.此时代码无误地运行。然而,将值增加到508& 508导致同样的错误重新出现。



我认为这个问题与子程序 NIGTEE 有关,因为当我

我尝试使用菜单项目>>将堆栈大小增加到最大值。设置>>链接>>>>>>>><预设&提交
但这没有什么区别。



我该如何解决这个问题?



这是我的程序:

  PARAMETER(NHELE = 508,NVELE = 508)
参数(NHNODE = NHELE + 1,NVNODE = NVELE + 1)
参数(NTOTALELE = NHELE * NVELE)

DIMENSION MELE(NTOTALELE,4)

CALL NIGTEE(NHELE,NVELE,NHNODE,NVNODE,NTOTALELE,MELE)
$ b $ 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)
DIMEL 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)
节点(2)= NM(I,J + 1)
节点(3)= NM(I + 1,J + 1)
节点(4)= NM + 1,J)
KK = KK + 1
DO 5 0 II = 1,4
50 MELE(KK,II)= NODE(II)

30继续
RETURN
END

$ b

谢谢。

解决方案

更新



这是您的实际问题。通过 NVNODE将 NM 数组声明为 NHNODE 单元格的二维数组行。如果是10,000乘以10,000,那么除了程序使用的任何其他内存之外,您将需要超过381兆字节的内存来单独分配此阵列。 (相比之下,如果数组是500乘500,那么相同的数组只需要大约1 MB的内存。)问题是,旧的Fortran会分配所有的数据直接在代码段或堆栈中的数组。 OS堆(大型对象的通用内存)的概念是在1977年发明的,但Fortran 77仍然没有任何构造来利用它。所以每次你的子程序被调用时,它都必须推栈指针为堆栈上381兆字节的空间腾出空间。这几乎肯定大于操作系统允许堆栈段的空间量,并且您正在溢出堆栈内存(因此获得

解决方案是从不同的地方分配内存。rel =noreferrer> stack overflow )。我知道在旧的Fortran中可以使用 COMMON 块来直接从代码段静态分配内存。你仍然不能动态分配更多的东西,所以你的子程序不能重入,但是如果你的子程序一次只被调用一次(看起来是这样),这可能是最好的解决方案。



更好的解决方案是转换到Fortran 90或更新的版本,并使用 ALLOCATE 关键字来动态分配堆上的数组而不是堆栈。然后你可以根据你的操作系统给你分配一个大块,但是你不必担心堆栈溢出,因为内存将来自另一个地方。



您可以通过在编译器中将其更改为MSB来解决此问题建议,但更好的解决方案是简单地修复代码。

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.

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

I've tried iteratively reducing the required values, until I reached 507 & 507. At this point the code runs without errors.

However, increasing the values to 508 & 508 causes the same error to reappear.

I think the problem is related to the subroutine NIGTEE, because when I rearrange the program without it, everything works fine.

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?

Here is my program:

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

Thanks.

解决方案

Update:

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

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

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.

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.

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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆