Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Stack Overflow in Fortran program

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.

like image 691
ghazooo Avatar asked Dec 17 '22 05:12

ghazooo


1 Answers

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.

like image 144
Daniel Pryden Avatar answered Jan 08 '23 20:01

Daniel Pryden