【问题标题】:Stackoverflow in Fortran subroutineFortran 子程序中的 Stackoverflow
【发布时间】:2011-10-20 19:45:16
【问题描述】:

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

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 次,并得到错误“程序异常 - 堆栈溢出”

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

【问题讨论】:

  • 您提供的信息无法给您答案。

标签: arrays fortran stack-overflow


【解决方案1】:

如果没有实际代码,这个问题很难诊断。子程序是否知道主程序中的循环和计数器或您调用子程序的次数?我猜测这两个特殊数组,您正在通过使用 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)

目前尚不清楚为什么会出现堆栈溢出,但我猜你终于达到了一个点,即你的数组开始占用太多内存。如果您提供更多信息,我可能会提供更多帮助。你的代码实际上是什么样子的?

【讨论】:

    【解决方案2】:

    真正的问题可能是“超出数组边界”错误——这表明存在错误,即导致程序尝试访问数组之外​​的数组元素的编码错误。非法内存访问可能会导致其他错误。将数组大小增加得比您认为的要大(如果您正在这样做的话)对于真正的问题来说是一个糟糕的补丁。我建议在继续之前解决数组边界错误。为什么索引小于 1 或大于数组的大小?请参阅@Yann 的答案。

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

    此外,如果有 20 个数组 array_1 (len) 到 array_20 (len),则使用单个数组 (len, 20) 的代码可能会更简洁。

    【讨论】:

      猜你喜欢
      • 2013-04-22
      • 1970-01-01
      • 2015-08-08
      • 2017-07-19
      • 1970-01-01
      • 2018-11-05
      • 2014-04-05
      • 2021-09-27
      • 1970-01-01
      相关资源
      最近更新 更多