Fortran子程序中的Stackoverflow

时间:2011-08-05 12:06:39

标签: arrays fortran stack-overflow

我有一个带有子程序的主程序,需要多次调用。主程序如下:

program main
 open output file
   do i = 1, 20000
   read parameters par_1, par_2, ..., par_8
   call subroutine (par_1, .... , par_8)
   enddo
end program

子例程完成所有工作,我不想保存数组的值。它们主要用于存储中间结果。

子程序如下:

subroutine calcr
  real, dimension(5000) :: array_1, array_2, .... array_20
  read temperature into array_1
  read pH into array_2
  ...   
  store intermediate results into array_10
  sotre intermediate results into array_20
  ...
  make final calculations 
  write the results to the output file
  close files from which the data was read (temperature, pH...)
end subroutine

我发现我的20个阵列中有两个有问题。如果我将这两个数组的维度加倍,我可以毫无问题地运行程序两次。 程序停止,并显示错误消息“程序异常超出阵列数组”

如果我使用尺寸* 10,那么我可以运行程序10次并得到相同的错误。

但如果我采用维* 100,我只能运行程序大约30次并得到错误“程序异常 - 堆栈溢出”

我不知道问题可能在哪里,因为我以相同的方式对待所有数组,只有两个数组有这个问题。 谢谢 !

2 个答案:

答案 0 :(得分:2)

如果没有实际代码,很难诊断出这个问题。子程序是否知道主程序中的循环和计数器或者调用子程序的次数?我猜测这两个特殊的数组,你是通过使用i计算的索引来访问一个元素,i是主循环中的计数器。

您使用的是什么编译器?对于gfortran,有一个标志来测试数组是否超出范围,即read the answer to this question。对于其他编译器,可能有类似的标志。您可以使用这些标志进行编译,并希望您可以获得有关数组越界问题发生位置的更多信息,例如:你的编译器调用了这个

  

“程序异常超出数组绑定”

但没有提供导致问题的代码行的信息。

这是一个程序正在做我认为你正在做的事情:

module global
  integer :: nsubcalls=0 ! counter for the number of times stuff() is called
end module

subroutine stuff
  use global
  integer :: isub
  integer :: nelements = 5000
  real,dimension(5000) :: array_1

  do isub=1,nelements
     array_1(nsubcalls*nelements+isub) = isub
  end do

  nsubcalls = nsubcalls +1 
end subroutine

program main 

  use global 
  integer :: i

  nsubcalls=0
  do i=0,20000
     print *,"i = ",i
     call stuff()
  end do

end program

如果我编译它,就像这样:

 gfortran -fbounds-check test2.f90

我得到以下输出:

i =            0
i =            1
At line 15 of file test2.f90
Fortran runtime error: Array reference out of bounds for array 'array_1', upper bound of dimension 1 exceeded (5001 > 5000)

目前还不清楚为什么你的堆栈溢出,但我猜你终于达到了你的阵列占用太多内存才能启动的程度。如果您提供更多信息,我可能会提供更多帮助。你的代码实际上是什么样的?

答案 1 :(得分:2)

真正的问题可能是“数组边界超出”错误 - 这是一个错误的指示,即导致程序尝试访问数组外部的数组元素的编码错误。非法内存访问可能会导致其他错误。增加数组大小比你认为需要的大(如果你正在做的那样)对于真正的问题是一个糟糕的补丁。我建议在继续之前解决数组边界错误。为什么索引要么<1还是大于数组的大小?看@Yann的答案。

在第二部分中,您是否意味着您将尺寸增加10倍和100倍?某些操作系统具有令人惊讶的小型默认堆栈大小。如果确实存在堆栈溢出问题,则有三种解决方案可供选择:1)重新设计程序以使用较小的阵列,2)增加堆栈大小,或3)将数组从堆栈移动到堆。方法2取决于您的操作系统。大多数编译器提供编译选项,以从堆栈中移动所有数组或大数组,例如,请参阅forrt1: severe (170): Program Exception - stack overflow

此外,使用二十个数组array_1(len)到array_20(len),代码可能更清晰,只有一个数组(len,20)。