Assertions in Fortran

2020-07-14 12:30发布

问题:

Does Fortran have a standard function/keyword equivalent for C assert?

I could not find assert mentioned in Fortran2003 standard I have. I have found few ways how to use pre-processor, but in this answer it is suggested to write own assertions. Is it possible to create such user function/subroutine without using pre-processor?

I expect that these assertions are disabled for release builds.

回答1:

To my knowledge, there is no such statement or function/subroutine in Standard Fortran. But - as you have said - you can use your own subroutines/function and/or OOP in Fortran to realize this goal. See Arjen Markus' excellent paper on this topic.



回答2:

Conditional compilation has never really caught on in Fortran and there isn't a standard pre-processor. If getting your pre-processor to switch in and out a dummy assert routine isn't something you want to tackle you could ...

Define a global parameter such as:

logical, parameter :: debugging = .true.

If you are of a nervous disposition you could put this into a module and use-associate it into every scope where it is needed; to my mind using a global parameter seems a reasonable approach here.

Then write guarded tests such as

if (debugging) call assert(...)

Once you want to release the code, set the value of debugging to .false. I expect, though I haven't tested this so you may care to, that any current Fortran compiler can remove dead code when it encounters an expression equivalent to

if (.false.) call assert(...)

and that your released code will pay no penalty for a dummy call to an assert routine.

Another approach might be to create a module, let's call it assertions, along these lines:

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

You could then rename the subroutines when you use-associate them, such as:

use, non_intrinsic :: assertions, assert=>assert_dbg

and change that to assert=>assert_prd when you want to turn off assertion checking. I suspect though that compilers may not eliminate the call to the empty subroutine entirely and that your production code might pay a small penalty for every assertion it encounters.

Beyond this, see the paper by Arjen Markus that @AlexanderVogt has referred you to.



回答3:

For fixed form sources, one can use -fd-lines-as-comments for release builds and -fd-lines-as-code for debug build (Intel Fortran -d-lines) and use custom assert:

D      if (assert_condition) then
D         write(*,*) 'assert message'
D         call exit(1)
D      endif