【问题标题】:Segfault with allocated string array in FortranFortran中分配字符串数组的段错误
【发布时间】:2020-01-23 20:40:19
【问题描述】:

我试图循环传递给 Fortran 程序的所有参数,参数的数量各不相同。因此,我使字符串数组可分配。

但是,一旦我开始说循环,如果给出任何参数,我就会得到一个段错误。

有一个可分配的字符串数组有什么问题吗?

代码:

program read_args

implicit none
character(len=999), allocatable :: args(:)
integer, allocatable :: i, nargs

nargs=command_argument_count()

if ( nargs == 0 ) then
    print*, 'err: no arguments or options'
    stop
end if

allocate(args(1:nargs))

print*, nargs, size(args(:))
do i=1,nargs
    call getarg(i,args(i))
    args(i)=trim(adjustl(args(i)))
end do

end program

打印参数的数量和数组大小,一旦我尝试读取参数,就会出现段错误。

编译器,gfortran - gcc , v8.3.0 on debian 10

(为了避免 XY 问题:想法是检查参数列表中的选项标志以及获取所有应该处理的文件名)

结果:

$ ./a.out
err: no arguments or options

$ ./a.out arg1 arg2
2  2
<Segfault>

【问题讨论】:

  • 这确实解决了它。我从没想过这个选项甚至在没有明确定义时被激活(即integer, allocatable :: i(:))。在更大的程序中,我在该行上混合了可分配(向量、数组)和标量值。你能进一步解释一下吗?我也很乐意接受这个作为答案,这样主题就可以结束了 - 独立于任何解释。
  • i 从未在此程序中分配。您可能知道,对可分配变量的内在赋值会导致它被分配到表达式的形状/长度,但用作 DO 控制变量不是内在赋值,因此不适用。
  • @SteveLionel 我不是,甚至不知道rank=0 的变量可能需要分配。谢谢你的解释!对于未来的读者:自动分配是 Fortran 2003 标准。更多详情here.

标签: arrays string fortran segmentation-fault allocation


【解决方案1】:

正如 cmets 所说,这个程序中的问题是在 do 构造中使用了未分配的变量 i,而不是在构造中使用了字符数组。

我们可以准确地解释为什么这种使用 i 是有问题的。

do i=1,nargs

我们知道i 是“do 变量”(Fortran 2018, 11.1.7.2)。在这样的 do 构造中,我们知道(Fortran 2018, 11.1.7.4.1)作为循环处理的一部分:

DO 变量被定义为初始参数的值

那么,这个“定义”是否首先涉及分配i

它没有。这与作为内在分配一部分的显式分配过程形成对比,例如(例如有效的nargs=command_argument_count())。在未分配 i 的情况下不允许这种“被定义”(Fortran 2018, 5.4.10):

不得引用或定义未分配的可分配变量。

i 的定义与将i 作为具有初始参数的内在赋值的目标不同。

一般来说,具有诸如inargs 之类的可分配标量可能很有用,但在这个问题的情况下,不会出现这样的问题:从它们中删除allocatable 属性不会改变逻辑.或者,i 可以在输入 do 构造之前显式分配(无需为其赋值)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-02-11
    • 1970-01-01
    相关资源
    最近更新 更多