问题描述
我看到了这个问题:
以及接受的答案让我质疑我是否安全地编写了以下函数(不允许内存泄漏)
function getValues3D(this)result(vals3D)
implicit none
type(allBCs),intent(in):: this
real(dpn),dimension(:,:,:),pointer :: vals3D
integer,dimension(3):: s
if(this%TF3D)then
s =形状(this%vals3D)
if(associated(this%vals3D))then
stop可能的内存泄漏 - p已关联
endif
allocate(vals3D(s(1 ),s(2),s(3)))
vals3D = this%vals3D
else; call propertyNotAssigned('vals3D','getValues3D')
endif
end function
当我运行我的代码时,会显示此警告,但如果它以前(对此函数)已设置,那么不应将这个%vals3D
关联起来吗?我目前遇到内存错误,他们开始显示,当我介绍一个新的模块与此功能。
任何帮助,非常感谢。
我认为我不够具体。我想做下面的课,并且知道如何在记忆方面安全地实施课程。即:
$ b $ pre $ 模块vectorField_mod
使用constants_mod
隐式无
类型vecField1D
private
real(dpn),dimension(:),pointer :: x
logical :: TFx = .false。
结束类型
包含
子程序setX(this,x)
隐式无
类型(vecField1D),intent(inout): :this
real(dpn),dimension(:),target :: x
allocate(this%x(size(x)))
this%x = x
this %TFx = .true。
结束子程序
函数getX(this)结果(res)
隐式无
实数(dpn),维(:),指针:: res
类型(vecField1D),intent(in):: this
voidify(res)
allocate(res(size(this%x)))
if(this%TFx)then
res = this%x
endif
结束函数
结束模块
下面的代码测试这个模块:
程序testVectorField
使用constants_mod
使用vectorField_mod
隐式无
整数,参数:: Nx = 150
real(dpn),parameter :: x_0 = 0.0
real(dpn),参数: :x_N = 1.0
real(dpn),parameter :: dx =(x_N_x_0)/ dble(Nx-1)
real(dpn),dimension(Nx):: x =(/( x_0 + dble(i)* dx,i = 0,Nx-1)/)
real(dpn),dimension(Nx):: f
real(dpn),dimension(:),pointer :: fp
type(vecField1D):: f1
integer :: i
do i = 1,Nx
f(i)= s in(x(i))
enddo
do i = 1,10 ** 5
call setX(f1,f)!
f = getX(f1)!我应该使用这个吗?
fp = getX(f1)!或这个?
fp => getX(f1)!甚至这个?
enddo
end program
目前,我在windows上运行。当我CTR-ALT-DLT和查看性能时,随着每次循环迭代,物理内存使用率增加会增加。这就是为什么我认为我有内存泄漏。
所以我想让我的问题得到解决:这是内存泄漏吗? (内存随着上述每种情况而增加)。如果是这样,有没有办法避免内存泄漏,同时仍然使用指针?如果不是的话,那么发生了什么事情,我应该关心,并且有办法减少这种行为的严重性吗?
对于最初的模糊问题抱歉。我希望这是更重要的。
您真的只限于Fortran 90吗?在Fortran 2003中,你可以使用一个可分配的函数结果。这更安全。使用指针函数结果,不管你是否有这段代码的内存泄漏,都取决于你如何引用你不显示的函数。如果你必须从一个过程返回一个指针,那么通过一个子例程参数返回它会更安全。
但是...
这个函数没有意义。在之后,您已经将它引用为上一行中的SHAPE的参数,因此测试此%vals3D` 的关联状态没有意义。如果指针组件被解除分配(或者有未定义的指针关联状态),那么您不能引用它。
另外,如果指针组件相关联,你可能会错误地将代码转录到问题上吗?
如果你简单地删除整个if结构,从 if(associated(this%vals3D))...
开始,那么你的代码可能是合理的。
但是...
this% TF3D
为true,那么此%vals3D
必须关联。
array_ptr => getValues3D(foo)
! ^
! |
! +这个小角色非常重要。
忘记那个小角色,你正在使用正常的赋值。在读取代码时,语法上有效,很难挑出差异,在这种情况下,除了使用指针的常见缺陷之外(例如,您需要DEALLOCATE),在可能最糟糕的时刻之前可能未检测到内存损坏或泄漏的来源array_ptr在重用之前或超出范围)。这就是为什么返回指针结果的函数被认为是有风险的。
$ b
你的测试代码中有一个循环。 ALLOCATE被调用了很多 - 在 setter和getter中。匹配的DEALLOCATE语句在哪里?
I saw this question:
and the accepted answer made me question if I wrote the following function safely (without allowing a memory leak)
function getValues3D(this) result(vals3D)
implicit none
type(allBCs),intent(in) :: this
real(dpn),dimension(:,:,:),pointer :: vals3D
integer,dimension(3) :: s
if (this%TF3D) then
s = shape(this%vals3D)
if (associated(this%vals3D)) then
stop "possible memory leak - p was associated"
endif
allocate(vals3D(s(1),s(2),s(3)))
vals3D = this%vals3D
else; call propertyNotAssigned('vals3D','getValues3D')
endif
end function
This warning shows up when I run my code, but shouldn't my this%vals3D
be associated if it was previously (to this function) set? I'm currently running into memory errors, and they started showing up when I introduced a new module with this function in it.
Any help is greatly appreciated.
I think I wasn't specific enough. I would like to make the following class, and know how to implement the class, safely in terms of memory. That is:
module vectorField_mod
use constants_mod
implicit none
type vecField1D
private
real(dpn),dimension(:),pointer :: x
logical :: TFx = .false.
end type
contains
subroutine setX(this,x)
implicit none
type(vecField1D),intent(inout) :: this
real(dpn),dimension(:),target :: x
allocate(this%x(size(x)))
this%x = x
this%TFx = .true.
end subroutine
function getX(this) result(res)
implicit none
real(dpn),dimension(:),pointer :: res
type(vecField1D),intent(in) :: this
nullify(res)
allocate(res(size(this%x)))
if (this%TFx) then
res = this%x
endif
end function
end module
Where the following code tests this module
program testVectorField
use constants_mod
use vectorField_mod
implicit none
integer,parameter :: Nx = 150
real(dpn),parameter :: x_0 = 0.0
real(dpn),parameter :: x_N = 1.0
real(dpn),parameter :: dx = (x_N - x_0)/dble(Nx-1)
real(dpn),dimension(Nx) :: x = (/(x_0+dble(i)*dx,i=0,Nx-1)/)
real(dpn),dimension(Nx) :: f
real(dpn),dimension(:),pointer :: fp
type(vecField1D) :: f1
integer :: i
do i=1,Nx
f(i) = sin(x(i))
enddo
do i=1,10**5
call setX(f1,f) !
f = getX(f1) ! Should I use this?
fp = getX(f1) ! Or this?
fp => getX(f1) ! Or even this?
enddo
end program
Currently, I'm running on windows. When I CTR-ALT-DLT, and view performance, the "physical memory usage histery" increases with every loop iteration. This is why I assume that I have a memory leak.
So I would like to repose my question: Is this a memory leak? (The memory increases with every one of the above cases). If so, is there a way I avoid the memory leak while still using pointers? If not, then what is happening, should I be concerned and is there a way to reduce the severity of this behavior?
Sorry for the initial vague question. I hope this is more to the point.
Are you really restricted to Fortran 90? In Fortran 2003 you would use an allocatable function result for this. This is much safer. Using pointer function results, whether you have a memory leak with this code or not depends on how you reference the function, which you don't show. If you must return a pointer from a procedure, it is much safer to return it via a subroutine argument.
BUT...
This function is pointless. There's no point testing the association status of this%vals3D` after you've referenced it as the argument to SHAPE in the previous line. If the pointer component is disassocated (or has undefined pointer association status), then you are not permitted to reference it.
Further, if the pointer component is associated, all you do is call stop!
Perhaps you have transcribed the code to the question incorrectly?
If you simply delete the entire if construct starting with if (associated(this%vals3D))...
then your code may make sense.
BUT...
- if
this%TF3D
is true, thenthis%vals3D
must be associated. when you reference the function, you must use pointer assignment
array_ptr => getValues3D(foo) ! ^ ! | ! + this little character is very important.
Forget that little character and you are using normal assignment. Syntactically valid, difficult to pick the difference when reading code and, in this case, potentially a source of memory corruption or leaks that might go undetected until the worst possible moment, in addition to the usual pitfalls of using pointers (e.g. you need to DEALLOCATE array_ptr before you reuse it or it goes out of scope). This is why functions returning pointer results are considered risky.
Your complete code shows several memory leaks. Every time you allocate something that is a POINTER - you need to pretty much guarantee that there will be a matching DEALLOCATE.
You have a loop in your test code. ALLOCATE gets called a lot - in both the setter and the getter. Where are the matching DEALLOCATE statements?
这篇关于Fortran 90函数返回指针的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!