在这里,我知道A只是一个长度为170的一维数组。
subroutine gonewrong(q,e,A)
implicit none
integer, dimension(:) :: q
integer, dimension(:,:), intent(in) :: e
integer, dimension(size(e,1)*2), intent(out) :: A
print *, A(2)
end subroutine gonewrong
例如,当我尝试找到A(2)时,它会给我一个分段错误! e具有维度(85,2)。
是不是因为我在用来编译它的程序中将A声明为可分配数组?
我使用的程序:
program prog_1
use module_1
implicit none
integer::qm,a,b,c
integer,allocatable,dimension(:)::q
integer,allocatable,dimension(:,:)::e
!integer, dimension(size(e,1)*2) :: A
a = 5
b = 3
c = 10
allocate(q(a+c))
allocate(e(a+b*c,2))
call subr1(a,b,c,qm,q,e) !Outputs are qm,q and e.
call gonewrong(q,e,A) !gonewrong takes q and e as arguments
end program prog_1
答案 0 :(得分:1)
需要考虑的另一个问题是声明:
integer,allocatable,dimension(:,:)::e
integer, dimension(size(e,1)*2) :: A
e
的大小在声明A
时未定义(零?)。如果A
的大小取决于e
的大小,则需要在编译时修复e
的大小或将A
设置为可分配且单独分配一旦设置了e
的大小,就分配它。需要注意的是A
不会动态调整其大小,因为e
的大小会发生变化。在这种情况下,看起来A
声明为零长度,因为size(e)
返回零,因为只定义了e
的形状,而不是它的大小。引用A(2)
可能会导致分段违规(读取数组的末尾),这与您正在观察的内容一致。
除此之外:很多人从动态语言进入Fortran并没有意识到Fortran例程被分成至少三个“区域”;包含用于导入外部资源的use
语句的初始部分,声明参数和局部变量的声明部分,以及放置可执行语句的例程的主体(鼓励学生阅读语言规范;我是为了实用主义而在这里概括)。 implicit
语句将导入与声明分开,按照惯例,我使用裸continue
语句将声明与可执行语句分开。 continue
被认为是可执行的,因此如果声明出现在第一个continue
之后,编译器应该会抱怨。
答案 1 :(得分:0)
错误很明显:
integer::qm,a
使a
成为一个整数(标量)。
子程序需要一个数组:
integer, dimension(size(e,1)*2), intent(out) :: A
所以你在那里传递错误的东西:
call gonewrong(q,e,A) !gonewrong takes q and e as arguments
因为Fortran 不区分大小写!您将标量整数a/A
传递给期望数组的子例程。
在(:)
的子例程中使用相同的A
会更好,并让编译器告诉您正在发生错误。
参数是一个数组,所以你必须在那里传递一个数组。
注意:在原始代码中,您已将此行注释掉
! integer, dimension(size(e,1)*2) :: A
当你有两行
时integer::qm,a
integer, dimension(size(e,1)*2) :: A
程序无法编译,因为a/A
被声明了两次。
我不太清楚你的实际意图。你的评论
!gonewrong takes q and e as arguments
实在令人困惑。这三件事都是gonewrong
的论点。 q
,e
和A
。