【发布时间】:2017-09-06 23:17:17
【问题描述】:
Fortran 是否有与 C assert 等效的标准函数/关键字?
我找不到我拥有的 Fortran2003 标准中提到的assert。我发现了一些如何使用预处理器的方法,但是在这个answer 中建议编写自己的断言。是否可以在不使用预处理器的情况下创建这样的用户函数/子程序?
我希望在发布版本中禁用这些断言。
【问题讨论】:
标签: fortran preprocessor assert
Fortran 是否有与 C assert 等效的标准函数/关键字?
我找不到我拥有的 Fortran2003 标准中提到的assert。我发现了一些如何使用预处理器的方法,但是在这个answer 中建议编写自己的断言。是否可以在不使用预处理器的情况下创建这样的用户函数/子程序?
我希望在发布版本中禁用这些断言。
【问题讨论】:
标签: fortran preprocessor assert
条件编译在 Fortran 中从未真正流行起来,并且没有标准的预处理器。如果让您的预处理器切换进出虚拟断言例程不是您想要解决的问题,您可以...
定义一个全局参数如:
logical, parameter :: debugging = .true.
如果你有紧张的性格,你可以把它放到一个模块中,并在需要它的每个范围内使用关联它;在我看来,在这里使用全局参数似乎是一种合理的方法。
然后编写受保护的测试,例如
if (debugging) call assert(...)
一旦你想发布代码,将debugging 的值设置为.false. 我希望,虽然我没有测试过,所以你可能会关心,任何当前的 Fortran 编译器都可以在遇到死代码时删除它等价于
if (.false.) call assert(...)
并且您发布的代码不会因为对assert 例程的虚拟调用而付出代价。
另一种方法可能是创建一个模块,我们称之为assertions,大致如下:
module assertions
contains
subroutine assert_prd(args)
! declare args
end subroutine
subroutine assert_dbg(args)
! declare args
! now do do some assertion checking and exception raising, etc
end subroutine
end module assertions
然后,您可以在使用关联时重命名子程序,例如:
use, non_intrinsic :: assertions, assert=>assert_dbg
当你想关闭断言检查时,将其更改为assert=>assert_prd。我怀疑编译器可能不会完全消除对空子例程的调用,并且您的生产代码可能会为它遇到的每个断言付出一点代价。
除此之外,请参阅 @AlexanderVogt 推荐给您的 Arjen Markus 的论文。
【讨论】:
interface assert 和 module procedure assert_dbg,您可以将其更改为 module procedure assert_prd。
据我所知,标准 Fortran 中没有这样的语句或函数/子例程。但是 - 正如你所说 - 你可以在 Fortran 中使用你自己的子例程/函数和/或 OOP 来实现这个目标。有关此主题,请参阅 Arjen Markus 的出色 paper。
【讨论】:
对于固定形式的源代码,可以使用-fd-lines-as-comments 进行发布构建,使用-fd-lines-as-code 进行调试构建(Intel Fortran -d-lines)
并使用自定义断言:
D if (assert_condition) then
D write(*,*) 'assert message'
D call exit(1)
D endif
【讨论】: