Error handling 纯Fortran程序中的I/O

Error handling 纯Fortran程序中的I/O,error-handling,io,fortran,gfortran,fortran95,Error Handling,Io,Fortran,Gfortran,Fortran95,我试图将错误检查纳入我正在编写的纯过程中。我想要一些像: pure real function func1(output_unit,a) implicit none integer :: a, output_unit if (a < 0) then write(output_unit,*) 'Error in function func1: argument must be a nonnegative integer. It is ', a

我试图将错误检查纳入我正在编写的纯过程中。我想要一些像:

pure real function func1(output_unit,a)
    implicit none
    integer :: a, output_unit

    if (a < 0) then
        write(output_unit,*) 'Error in function func1: argument must be a nonnegative integer. It is ', a
    else
    func1 = a/3

    endif
    return
end function func1
纯实函数func1(输出单位a)
隐式无
整数::a,输出单位
如果(a<0),则
函数func1中的write(output_unit,*)”错误:参数必须是非负整数。这是一个
其他的
func1=a/3
恩迪夫
返回
结束函数func1

但是,纯函数不允许将IO语句传递到外部文件,因此我尝试将单元号传递给函数,例如,
output\u unit=6
,这是默认输出。格夫特兰仍然认为这是非法的。有办法解决这个问题吗?有没有可能使函数成为一个派生类型(而不是这里的内在类型
real
),在出现错误时输出一个字符串?

我自己找到了一个答案,非常详细。它使用了被认为是“过时”的东西,但仍然起作用;这叫做交替返回。将该过程作为子例程编写,因为它不适用于函数

pure real subroutine procA(arg1)
    implicit none
    integer :: arg1

    if (arg < 0) then
        return 1 ! exit the function and go to the first label supplied
                 ! when function was called. Also return 2, 3 etc.
    else
        procA = ... ! whatever it should do under normal circumstances
    endif
endsubroutine procA

.... 

! later on, procedure is called
num = procA(a, *220)

220 write(6,*) 'Error with func1: you've probably supplied a negative argument'
纯实数子程序procA(arg1) 隐式无 整数::arg1 如果(arg<0),则 返回1!退出函数并转到提供的第一个标签 ! 当函数被调用时。还返回2、3等。 其他的 procA=!无论它在正常情况下应该做什么 恩迪夫 endsubroutine程序 .... ! 稍后,调用该过程 num=procA(a,*220) 220写入(6,*)'func1错误:您可能提供了一个否定参数' 更好的可能是eriktous所建议的——让过程返回一个状态,可能是一个逻辑值或一个整数,让程序在每次调用过程后检查这个值。如果一切顺利,继续。否则,打印相关的错误消息


欢迎评论。

您不是第一个遇到此问题的人,我很高兴地说,标准中的此缺陷将在Fortran 2015中得到修复。如(第6页标题“已批准的标准变更”)所述,“应取消对
程序中出现
错误停止
语句的限制”

Fortran 2008标准在一些新的并行计算特性的上下文中包含了
错误停止
语句。它发出错误信号,并使所有进程尽快停止。目前,
pure
过程中既不允许使用
stop
语句,也不允许使用
error stop
语句,因为它们显然不是线程安全的。实际上,在发生内部错误的情况下,这是不必要的限制

根据编译器的不同,您可能需要耐心等待实现。我知道英特尔在他们的ifort编译器中提供了它。(“F2015:纯/基本程序中停止和错误停止的提升限制”)

可供替代的 对于另一种方法,您可以看一看,不过在您的情况下,这可能有点棘手,因为您必须更改
do concurrent
关键字,而不仅仅是
pure

(正确答案结束) 如果脏手是一种选择。。。 与此同时,你可以做一些残忍的事情,比如

pure subroutine internal_error(error_msg)
    ! Try hard to produce a runtime error, regardless of compiler flags.
    ! This is useful in pure subprograms where you want to produce an error, 
    ! preferably with a traceback.
    ! 
    ! Though far from pretty, this solution contains all the ugliness in this 
    ! single subprogram.
    ! 
    ! TODO: replace with ERROR STOP when supported by compiler
    implicit none

    character(*), intent(in) :: error_msg

    integer, dimension(:), allocatable :: molested

    allocate(molested(2))
    allocate(molested(2))
    molested(3) = molested(4)
    molested(1) = -10
    molested(2) = sqrt(real(molested(1)))
    deallocate(molested)
    deallocate(molested)
    molested(3) = molested(-10)
end subroutine internal_error

如果有人问,您不是从我这里得到的。

从技术上讲,“纯”过程不会以任何方式修改其环境或任何操作数。所以它不应该打印到屏幕上?它是否可以打印到主程序可以访问并打印到屏幕的内部字符串?不过,这太迂回了。@SamuelTan-Nope-no纯内存中没有任何类型的I/O。简言之,它不改变任何东西(变量、局部或全局)、不保存,也不I/O任何东西(将它所做的事情列成一个列表会更容易:\…;)通常绕过这些限制的方法是将函数转换为子例程,并添加一个额外的参数来返回状态(此参数可以使用派生类型,以返回错误代码和错误文本)。@HotLicks。我在
do concurrent
块中使用此函数,因此它必须是纯的(我必须显式地将
pure
放在前面,否则编译器会抱怨).Argh!请不要使用此选项。将其标记为“过时”是有原因的。当前标准建议以下选项作为替代选项(基本上与我的建议相同):
返回时,在SELECT CASE构造中使用的返回代码也可以达到同样的效果。
残酷的子例程是不必要的复杂。你也可以只编写一个外部子例程,然后放在一个纯粹的接口中。非常简单。这符合标准吗?当然不是,但我不认为是考虑到它所做的是有害的。当它中止程序时,它不会以任何方式破坏其余的运行。标准(尤其是95标准)也不会指定当你将一个负数的平方根设为平方根时会发生什么。在符合IEEE标准的Fortran 2003 CPU中,只有当你确实设置了正确的标志以启用对IEEE异常的暂停时,你才有一些保证。但人们通常不希望在任何地方都这样。我当然不会在运行我的主代码时暂停浮点异常。