Pointers Fortran解除分配
我目前正试图用Fortran编写一个小子程序,当我的程序出现错误时,即加载文件失败或所需文件不存在时,释放内存中所有分配的变量。此时,必须终止执行,但并非所有可分配项都必须分配(这取决于错误出现的代码位置),因此我无法对所有可分配项进行清理-取消分配 我目前的做法如下:Pointers Fortran解除分配,pointers,fortran,Pointers,Fortran,我目前正试图用Fortran编写一个小子程序,当我的程序出现错误时,即加载文件失败或所需文件不存在时,释放内存中所有分配的变量。此时,必须终止执行,但并非所有可分配项都必须分配(这取决于错误出现的代码位置),因此我无法对所有可分配项进行清理-取消分配 我目前的做法如下: SUBROUTINE Cleanup(A) REAL(8), ALLOCATABLE, DIMENSION(:) :: A IF (ALLOCATED(A)) THEN DEALLOCATE(
SUBROUTINE Cleanup(A)
REAL(8), ALLOCATABLE, DIMENSION(:) :: A
IF (ALLOCATED(A)) THEN
DEALLOCATE(A)
END IF
END SUBROUTINE
并为每个可分配项调用“清理”。问题是我的变量并非都是维1。我在其中一些中有多达三个维度
我首先想到为不同的维度编写3个不同的子程序,并使用重载,但这似乎不是很优雅
然后我想到也许我可以传递一个指针,而不是实际的参数a,但我已经在谷歌上搜索过了,似乎你无法通过指针释放目标变量
关于如何正确地做到这一点有什么想法吗
谢谢。我的方法是结合以下几点:
SUBROUTINE Cleanup(A)
REAL(8), ALLOCATABLE, DIMENSION(:) :: A
IF (ALLOCATED(A)) THEN
DEALLOCATE(A)
END IF
END SUBROUTINE
- 从Fortran 95开始,在过程完成时分配的所有本地未保存的可分配变量都会自动取消分配。这是否适用取决于DLL的调用方式,因此也取决于您是否能够实际构造事物,使所有可分配项都是未保存的局部变量
- 从Fortran 2003(或Fortran 95+可分配TR-此语言级别在维护的Fortran编译器中得到广泛支持)起,传递给INTENT(OUT)可分配伪参数的可分配实际参数将在过程开始执行之前自动解除分配。问题中的清理例程只需要将伪参数声明添加为INTENT(OUT),然后就不需要进行IF测试或取消分配。您仍然需要为需要清理的每个类型和等级编写例程
- 与前面类似,传递给INTENT(OUT)伪参数的派生类型变量的可分配组件将自动解除分配。因此,您可以将所有可分配变量作为派生类型对象中的组件收集在一起。然后,清理只涉及将该对象传递给带有意图(OUT)伪对象的过程。此处的INTENT(OUT)还将具有默认初始化的组件重置回其“默认”值。也许此时还需要手动执行其他清理(关闭文件等)
- 另一种方法是,再次使用派生类型,将所有变量作为组件,使派生类型对象本身可分配。当您需要清理时,只需释放一个对象,它的组件就会自动释放。Fortran 2003允许从此类事件触发最后一个过程,前提是此时需要进行其他清理
TYPE MyType
REAL, ALLOCATABLE :: variable_one(:)
INTEGER, ALLOCATABLE :: variable_two(:)
...
END TYPE MyType
意图(外)假人
可分配对象
TYPE(MyType), ALLOCATABLE :: object
ALLOCATE(object)
ALLOCATE(object%variable_one(...))
ALLOCATE(object%variable_two(...))
...
IF (things_have_gone_wrong) DEALLOCATE(object)
当执行终止时,代码使用的所有资源都会以任何方式自动释放,因此您不必担心显式地释放它们。我知道Fortran会自动释放内存,但在本例中,我正在编写一个从Labview调用的dll,所以这就是管理内存的人。当dll出现错误时,Labview突然停止,如果我尝试重新执行,它将显示消息:“Array已分配”并关闭。这意味着内存未正确释放。注意:
real(8)
不保证为8字节。一种可移植的方法是使用ISO_FORTRAN_ENV,real(real64)
作为64位。我发现解决此问题的另一种方法是使用预处理器宏:#定义清理(A)如果(分配(A))取消分配(A)调用时,清理会执行此任务。