【问题标题】:Segmentation Fault - fortran 90 - bisection subroutine分段错误 - fortran 90 - 对分子例程
【发布时间】:2013-02-11 14:11:40
【问题描述】:
program bisect
real(8) ::  output
call bisection(3.d0,4.d0,2.d0,output)
print*, output
end program bisect

subroutine bisection(a,b,error,result)
real(8):: a,b,error,c,result
logical:: proceed
  proceed = .true.
  do while (proceed)
  if (sin(a)*sin(b).lt. 0.d0) then
     c=(a+b)/2
     if (sin(a)*sin(c).lt.0.d0) then
        b=c
     else
        a=c
     end if
  else  
     stop 'cannot be bisected'
  end if 

  if (abs(a-b).lt. error) then
     proceed = .false.
  end if
 end do
 result= a
end subroutine bisection

同一代码的一个版本上传here

这是我能想到的最小示例。这会在使用 gfortran 以及在网站上运行可执行文件时产生分段错误。

【问题讨论】:

    标签: segmentation-fault fortran90 bisection


    【解决方案1】:

    虚拟参数 a 和 b 与作为常量的实际参数相关联。常量是不可定义的——你的程序试图改变“3.0d0”或“4.0d0”的值。如果你的程序成功了,那么整个宇宙都会爆发混乱。

    我强烈推荐:

    • 使用模块过程。这允许编译器检查实际参数是否与虚拟参数一致。
    • 在您的虚拟参数定义中使用 INTENT 规范。这允许编译器检查需要修改的内容是否是可修改的,以及不可修改的内容是否不是。

    解决您的问题的方法是在您的主程序中使用适当的变量来保存初始值 3.0d0 和 4.0d0,并将这些可修改的变量传递给您的子程序。或者,您可以在子例程中创建虚拟参数的临时副本。在 F2003 中,VALUE 属性可用于自动执行此操作。

    虽然我们这样做了 - 在所有范围内都使用 IMPLICIT NONE。总是。

    【讨论】:

    • 子程序不把参数当作变量吗?例如,类似的东西可以在 python 中工作。
    • 一个令人信服的理由更喜欢 Fortran 而不是 Python。任何允许分配4.0 = 3.5 的语言都严重损坏。
    • @Mark:这至少值得商榷。如果有人要设计一个子程序,它应该是一段可重用的代码块;他们最好让它对输入参数的方式漠不关心/不可知论。你能说出Fortran做事方式带来的好处吗?我确实明白您关于更改常量值的观点,但是可以通过不允许使用 intent(out) 的参数使用文字来绕过这一点。
    • 为了清楚起见 - python 根本没有子例程。 Python 函数的参数没有意图类型。
    • 子例程确实将有问题的虚拟参数视为变量。这就是问题所在……他们不是! Fortran 的参数“传递”模型(在这种情况下 - 为简洁起见不精确)是“好像”虚拟参数和实际参数引用相同的底层事物。您不仅仅是在传递一个值——在虚拟参数和实际参数之间建立了一种关联形式。 (编译器如何实际实现是一个单独的问题——它可能传递对实际参数的引用,或者可能来回传递值——合法程序无法判断。)
    猜你喜欢
    • 1970-01-01
    • 2020-03-19
    • 1970-01-01
    • 2023-03-13
    • 2019-03-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-02-24
    相关资源
    最近更新 更多