1D阵列的分段错误

时间:2016-12-11 16:02:36

标签: arrays indexing segmentation-fault fortran

在这里,我知道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

2 个答案:

答案 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的论点。 qeA