【问题标题】:Fortran DEALLOCATEFortran 释放
【发布时间】:2013-05-02 10:00:34
【问题描述】:

我目前正在尝试在 Fortran 中编写一个小子例程,以在我的程序出现错误时释放内存中所有已分配的变量,即加载文件失败或所需文件不存在。此时,必须终止执行,但并非所有可分配对象都必须被分配(这取决于错误出现在代码的哪个位置),因此我无法进行清理以释放所有可分配对象。

我目前的做法如下:

SUBROUTINE Cleanup(A)

    REAL(8), ALLOCATABLE, DIMENSION(:) :: A

    IF (ALLOCATED(A)) THEN
        DEALLOCATE(A)
    END IF

END SUBROUTINE

并为每个可分配对象调用“清理”。问题在于,并非我的所有变量都是维度 1。我在其中一些中最多有三个维度。

我一开始想为不同的维度写3个不同的子程序并使用重载,但这似乎不是很优雅。

然后我想到也许我可以传递一个指针而不是实际的参数 A,但我已经用谷歌搜索了,似乎你不能通过指针释放目标变量。

关于如何正确执行此操作的任何想法?

谢谢。

【问题讨论】:

  • 执行终止时,您的代码使用的所有资源都会以任何方式自动释放,因此您不必担心显式释放它们。
  • 我知道 Fortran 会自动释放内存,但在这种情况下,我正在编写一个从 Labview 调用的 dll,所以这是管理内存的人。当 dll 出现错误时,Labview 突然停止,如果我尝试重新执行,它将显示消息:“数组已分配”并关闭。这意味着内存没有被正确释放。
  • 注意:real(8) 不保证为 8 个字节。一种可移植的方式是use ISO_FORTRAN_ENVreal (real64) 用于 64 位。

标签: pointers fortran


【解决方案1】:

我的方法将使用以下组合:

  • 从 Fortran 95 开始,在过程完成时分配的所有本地未保存的可分配变量都将自动解除分配。这是否适用取决于您的 DLL 是如何被调用的,因此您是否可以实际构建事物以使您的所有可分配对象都是未保存的本地对象。

  • 从 Fortran 2003(或 Fortran 95 + 可分配的 TR - 此语言级别在维护的 Fortran 编译器中得到广泛支持)可分配的实际参数传递给 INTENT(OUT) 可分配的虚拟参数将在过程开始之前自动释放执行。问题中的清理例程只需将虚拟参数的声明添加为 INTENT(OUT),然后就不需要 IF 测试或 DEALLOCATE。您仍然需要为需要清理的每种类型和等级编写例程。

  • 与前面类似,传递给 INTENT(OUT) 虚拟参数的派生类型变量的可分配组件将被自动释放。因此,您可以将所有可分配变量作为派生类型对象中的组件收集在一起。然后清理简单地涉及将该对象传递给具有 INTENT(OUT) 虚拟对象的过程。此处的 INTENT(OUT) 还将具有默认初始化的组件重置为其“默认”值。也许此时您还需要手动进行其他清理(关闭文件等)。

  • 另一种方法,再次使用将所有变量作为组件的派生类型,是使派生类型对象本身可分配。当您需要清理时,只需释放该对象 - 它的组件将自动释放。如果此时您还有其他清理工作要做,Fortran 2003 允许从此类事件触发最终过程。

派生类型方法还可以让您的 DLL 支持的多个实例同时独立激活(您只需拥有多个派生类型的对象)。

派生类型方法的示例,给出:

TYPE MyType
  REAL, ALLOCATABLE :: variable_one(:)
  INTEGER, ALLOCATABLE :: variable_two(:)
  ...
END TYPE MyType

INTENT(OUT) 假人

TYPE(MyType) :: object
ALLOCATE(object%variable_one(xxx))
ALLOCATE(object%variable_two(yyy))
...
IF (things_have_gone_wrong) CALL Cleanup(object)
...
SUBROUTINE Cleanup(arg)
  TYPE(MyType), INTENT(OUT) :: arg
END SUBROUTINE Cleanup

ALLOCATABLE 对象。

TYPE(MyType), ALLOCATABLE :: object
ALLOCATE(object)
ALLOCATE(object%variable_one(...))
ALLOCATE(object%variable_two(...))

...
IF (things_have_gone_wrong) DEALLOCATE(object)

【讨论】:

  • 我发现解决此问题的另一种方法是使用预处理器宏:#define Cleanup(A) IF (ALLOCATED(A)) DEALLOCATE(A) 调用时,Cleanup 会完成这项工作。跨度>
猜你喜欢
  • 2021-10-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-11-12
  • 2015-05-16
  • 2012-04-18
  • 2021-03-15
相关资源
最近更新 更多