【问题标题】:Segmentation error with 1D array一维数组的分割错误
【发布时间】:2016-12-11 16:02:35
【问题描述】:

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

【问题讨论】:

  • 您必须显示更多代码!它应该是可编译的。我们要看看你是怎么调用它的,程序怎么看接口的。子程序是否在模块中?应该是!
  • @VladimirF 是的,它在一个模块中并编译。我已经编辑了。
  • 等等,你怎么能在程序中将A 作为一个标量整数,然后将它传递给需要一个数组的子程序?那怎么可能编译?显示完整代码、整个模块、您使用的命令。使用一些调试标志进行编译 (-g -fcheck=all -Wall)。
  • @VladimirF 嗨,弗拉基米尔。好像你在我最后一次编辑之前看到了这篇文章。我使用的命令是 gfortran -o test.exe module_1.f90 prog_1.f90 -llapack - 我会向您展示完整的模块,但它相当长!而且我认为只有通过说明输出的尺寸来缩短它才会有帮助——毕竟,我调用的第一个子程序是独立工作的。
  • a 和 A 是一回事!!!

标签: arrays indexing segmentation-fault fortran


【解决方案1】:

另一个需要考虑的问题是在声明中:

integer,allocatable,dimension(:,:)::e
integer, dimension(size(e,1)*2) :: A

e 的大小在声明 A 时是未定义的(零?)。如果A 的大小取决于e 的大小,您需要在编译时修复e 的大小,或者将A 设置为可分配并在@987654328 的大小后单独分配它@ 已经设置好了。要点是A 不会随着e 的大小变化而动态调整其大小。在这种情况下,看起来A 声明的长度为零,因为size(e) 返回零,因为只定义了e 的形状,而不是它的大小。引用 A(2) 可能会引发分段违规(读取数组末尾),这与您观察到的内容一致。

除此之外:许多从动态语言进入 Fortran 的人没有意识到 Fortran 例程至少分为三个“区域”;包含用于导入外部资源的use 语句的初始部分,声明参数和局部变量的声明部分,以及放置可执行语句的例程主体(鼓励学究阅读语言规范;我在这里概括为了实用主义)。 implicit 语句将导入与声明分开,按照惯例,我用一个简单的continue 语句将声明与可执行语句分开。 continue 被认为是可执行的,因此如果声明出现在第一个 continue 之后,编译器应该会报错。

【讨论】:

  • 正如我所评论的,这是由 OP 在不关心的情况下更改问题中的代码引起的。我会把它恢复到明智的状态。
【解决方案2】:

错误很明显:

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。

【讨论】:

  • 非常感谢,我已修复大小写错误并将 a 更改为 L。
  • 没有大小写错误... Fortran/FORTRAN不区分大小写,所以除了认为有大小写的概念外,不可能出现大小写错误。
猜你喜欢
  • 1970-01-01
  • 2017-03-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多