我有一个带有子程序的主程序,需要多次调用。主程序如下:
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次并得到错误“程序异常 - 堆栈溢出”
我不知道问题可能在哪里,因为我以相同的方式对待所有数组,只有两个数组有这个问题。 谢谢 !
答案 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)。