fortran - 是否允许为另一个过程的可选参数传递一个不存在的假定形状数组?

标签 fortran standards undefined-behavior optional-parameters sanitizer

在这个最小的例子中,是否允许传递可选的虚拟参数 ytest_wrapper可能不是 present作为相应可选虚拟参数的实际参数 ytest ?

program main
    implicit none
    real :: x = 5.0
    call test_wrapper(x)

contains
    subroutine test_wrapper(x, y)
        implicit none
        real, intent(in) :: x
        real, dimension(:), intent(out), optional :: y
        call test(x, y)
    end subroutine test_wrapper

    subroutine test(x, y)
        implicit none
        real, intent(in) :: x
        real, dimension(:), intent(out), optional :: y
        if (present(y)) then
            y = x
        end if
    end subroutine test
end program
UndefinedBehaviourSanitizer 引发错误,表明它不是:https://godbolt.org/z/nKj1h6G9r
this Fortran standards document (第 311 页上的第 15.5.2.12 节“参数存在和对不存在参数的限制”)它说:
  1. An optional dummy argument that is not present is subject to the following restrictions.
    1. If it is a data object, it shall not be referenced or be defined. If it is of a type that has default initialization, the initialization has no effect.
    2. [...]
    3. [...]
    4. [...]
    5. A designator with it as the base object and with one or more subobject selectors shall not be supplied as an actual argument.
    6. [...]
    7. If it is a pointer, it shall not be allocated, deallocated, nullified, pointerassigned, or supplied as an actual argument corresponding to an optional nonpointer dummy argument.
    8. If it is allocatable, it shall not be allocated, deallocated, or supplied as an actual argument corresponding to an optional nonallocatable dummy argument.
    9. [...]
  2. Except as noted in the list above, it may be supplied as an actual argument corresponding to an optional dummy argument, which is then also considered not to be present.

我正在努力阅读该列表中的标准语,所以也许其中一项我不完全理解的项目禁止对假定形状的数组进行此操作?但在我看来,没有任何限制适用于这种情况。
但有趣的是,UBSan 似乎只在使用 dimension(:) 时才会引发错误。 ,即如果 y是一个假定形状的数组。其他类似 dimension(2) , dimension(n)添加尺寸参数 n , allocatable , pointer或没有似乎不会触发 UBSan。

最佳答案

对于没有可选虚拟参数的假定形状的使用没有额外的限制。允许有一个不存在的假定形状数组参数作为另一个过程中可选虚拟参数的实际参数,除非另一个限制阻止它。 (随后的虚拟参数将被视为不存在。)
如前所述,列出的限制都没有提到“假定形状”。特别是,你引用的那些(正如伊恩布什评论的)都不适用于这种情况。这使得“除非在上面的列表中注明,否则可能会提供......”是允许的。
如果您想进一步检查,假定形状参数 y每个子程序的 是一个普通的虚拟变量(并遵守 15.5.2.4 的规则)。
gfortran 7 没有提示。可能与此版本不理解有关-std=f2018 .
为了完整起见,让我们来看看为什么这些限制(所有,而不仅仅是问题中引用的那些)不适用。我不会引用限制,所以好奇的人需要查找那些不在问题中的文本。

  • 都没有 y不存在时被引用或定义(作为实际参数出现而不是引用或定义)。
  • 都没有 y出现在指针赋值中(也不是指针)。
  • 都没有 y是一个过程或过程指针。
  • ytest_wrapper不用作非可选虚拟参数的实际参数; ytest不用作实际参数。
  • test_wrapper实际参数是y本身,不是 y 的子对象; ytest不用作实际参数。
  • 虽然是数组,但 y用于引用基本过程的实际参数。
  • 都没有 y是一个指针。
  • 都没有 y是可分配的。
  • 都没有 y有一个长度类型参数(尤其是没有被查询的)。
  • 都没有 y用作选择器。
  • 都没有 y用于过程指示符。
  • 都没有 y用于过程组件引用。

  • 下面更简单的程序显示了相同的问题:
    program main
        implicit none
        call test_wrapper
    
    contains
        subroutine test_wrapper(y)
            real, dimension(1), intent(out), optional :: y
            call test(y)
        end subroutine test_wrapper
    
        subroutine test(y)
            real, dimension(:), intent(out), optional :: y
            if (present(y)) y=0  ! Used to silence unrelated warning
        end subroutine test
    end program
    

    关于fortran - 是否允许为另一个过程的可选参数传递一个不存在的假定形状数组?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/68046152/

    相关文章:

    c++ - 双循环变量 : unspecified or undefined? 的相等条件

    Fortran 的 findloc 与字符类型

    arrays - 什么是 'Bus error' 以及我的 Fortran 代码中的什么触发了它?

    pointers - Fortran2003:指向函数的过程指针返回指向多态类型的指针

    fortran - ifort 2015 中可能存在的错误

    c++ - 理解 C++ 标准的困惑

    c++ - 使用成员作为参数调用构造函数解析为变量定义

    html - 可以将链接 <a> 和图像 <img> 放在 h1 <h1> 中吗?

    c - C 标准是否强制要求平台不得定义超出标准中给出的行为

    c - 在 C 中使用大小为 10 的一维数组添加偶数