释放模块中声明的变量时出错
Posted
技术标签:
【中文标题】释放模块中声明的变量时出错【英文标题】:Error deallocating variable declared in module 【发布时间】:2013-07-01 10:34:21 【问题描述】:我的 Fortran 90 代码出现问题,涉及解除分配在模块中声明的数组,然后在子例程中分配和初始化。在我的程序中,我在 real*8, dimension(:), allocatable :: test
之类的模块中声明了一堆数组。然后,在一个初始化子程序中,我 use
模块,分配变量
allocate(test(8))
,并用test = 0.d0
初始化。
在此之后,我可以print*, test
并获得适当的输出:0.E+0 0.E+0 0.E+0 0.E+0 0.E+0 0.E+0 0.E+0 0.E+0
。此外,调用allocated(test)
会返回.TRUE.
。尽管如此,还是出了点问题。直接在调用allocate()
之后,调用sizeof(test)
返回0
,调用deallocate(test)
会引发以下错误:
lib-4422 : UNRECOVERABLE library error
A DEALLOCATE statement argument points to a portion of the
original allocation.
Original size in bytes for the argument is 512
Current size in bytes for the argument is 0
Segmentation fault
这一切都发生在一个更大的代码中,我在整个代码中都使用了这些数组,没有任何错误。我只是在寻找内存泄漏时试图在程序结束时释放内存时才注意到这个问题。我试图制作一个仅执行上述操作的简单程序(即,在模块中声明,在子程序中分配和初始化,然后打印数组并在同一个子程序中释放它)。然而,这个简单的代码可以正常工作并且没有错误地运行。因此,我对在较大代码的上下文中可能导致其行为不端的原因感到非常困惑。此外,如果在我较大的代码中,我将声明行从模块移动到子例程,一切都会正常运行。
任何建议将不胜感激!提前致谢,
~BCL
【问题讨论】:
注意sizeof
(供应商扩展)和size
(fortran内在)是不同的东西。听起来你的程序中有一些错误的部分破坏了内存。是时候使用常规调试技术了(使用完整的调试选项进行编译,使用静态和动态代码正确性工具,开始对分以隔离代码的问题部分)。
您是说,您在没有任何干预代码的情况下进行分配、sizeof、然后解除分配?那么deallocate的失败就很奇怪了。如果有中间代码,那么显然要查看该代码。按照 IanH 的建议,打开所有调试选项,尤其是。运行时下标(边界)检查。确保将您的过程放在模块中,以便检查参数的一致性。
【参考方案1】:
在处理不是单个子例程内部的数组时,我总是在声明它们时使用 pointer
属性而不是属性。在实践中,两者的工作方式相同。例如:
module Mod1
contains
subroutine sub1(Array)
!*** Declaration of Variables
implicit none
!*** External Variables - Arguments
real(kind=8), pointer, intent(inout) :: Array(:)
!*** Internal Variables
real(kind=8), allocatable :: InternalArr(:)
!*** Memory allocation
allocate(Array(1:8))
allocate(InternalArr(9:10))
!*** End of Subroutine
end subroutine sub1
end module Mod1
调用sub1
后,您的数组将在代码的任何位置保持其维度。您可以根据需要deallocate
和allocate
。
在使用pointer
之前,我遇到了一些类似您描述的问题,有人建议我改用pointer
。从那以后,我已经非常习惯以这种方式声明数组(如果它们打算保留在我一直使用allocatable
的同一个子例程或模块上),并且它一直被证明是控制数组的好方法。
我真的希望这会有所帮助...这是我的第一个答案 :) 编辑:我更正了示例代码中的一个小错误
【讨论】:
我的建议是相反的:使用allocatable
变量,除非您必须使用pointer
变量,因为您无法使用allocatable
完成任务。 allocatable
变量更安全,因为内存泄漏是不可能的。见***.com/questions/2300199/… 和***.com/questions/4023371/…
我知道这两个讨论,我同意你的观点,“可分配”更有效,因为“可分配”数组在内存方面是连续的。但是,正确分配和释放内存将防止遭受内存泄漏。事实上,我将“可分配”数组解除分配,就好像它们是“指针”一样。我想这是个人喜好的问题。无论如何,我只建议使用“指针”作为提示,因为它们在 fortran90 中更加通用。但我敢肯定,更有经验的 fortran 程序员可以提供更好的解决方案以上是关于释放模块中声明的变量时出错的主要内容,如果未能解决你的问题,请参考以下文章
将表中的单个值分配给 ORACLE PL/SQL 中声明的变量时出错
C 语言结构体 ( 结构体中嵌套一级指针 | 分配内存时先 为结构体分配内存 然后再为指针分配内存 | 释放内存时先释放 指针成员内存 然后再释放结构头内存 )