Fortran 90函数返回指针

查尔斯

我看到了这个问题:

Fortran动态对象

并且接受的答案使我产生疑问:我是否安全地编写了以下函数(不允许内存泄漏)

   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%vals3D如果以前(对此功能)设置了该代码,是否不应该将其关联?我目前遇到内存错误,当我引入一个带有此功能的新模块时,它们开始出现。

任何帮助是极大的赞赏。

我想我还不够具体。我想编写以下课程,并知道如何在内存方面安全地实现该课程。那是:

   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

以下代码在哪里测试此模块

   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

目前,我正在Windows上运行。当我单击CTR-ALT-DLT并查看性能时,“物理内存使用情况”随每次循环迭代而增加。这就是为什么我认为我有内存泄漏的原因。

因此,我想提出一个问题:这是内存泄漏吗?(以上每种情况下,内存都会增加)。如果是这样,有没有办法在仍然使用指针的情况下避免内存泄漏?如果不是,那么正在发生的事情,我应该关注并且有办法降低这种行为的严重性吗?

很抱歉最初的模糊问题。我希望这更重要。

伊恩

您真的受限于Fortran 90吗?在Fortran 2003中,您将为此使用可分配的函数结果。这样更安全。使用指针函数结果,此代码是否导致内存泄漏取决于您如何引用函数(未显示)。如果必须从过程中返回指针,则通过子例程参数返回它要安全得多。

但...

此功能毫无意义。在上一行中将它作为SHAPE的参数引用,没有任何必要测试此%vals3D`的关联状态如果指针组件已取消关联(或具有未定义的指针关联状态),则不允许您引用它。

此外,如果指针组件已关联,则您要做的就是停止呼叫!

也许您没有正确地将代码转录到问题上?


如果只是删除以if开头的整个if构造,if (associated(this%vals3D))...则您的代码可能有意义。

但...

  • 如果this%TF3D为true,则this%vals3D必须关联。
  • 引用该函数时,必须使用指针分配

    array_ptr => getValues3D(foo)
    !          ^
    !          |
    !          + this little character is very important.
    

    忘记那个小人物,您正在使用常规作业。语法上有效,在读取代码时很难发现差异,在这种情况下,除了使用指针的常见陷阱(例如,需要取消分配)外,还有可能导致内存损坏或泄漏的源头,直到最坏的时刻才可能被发现在您重用它之前,否则它会超出范围)。这就是为什么返回指针结果的函数被认为具有风险的原因。


您的完整代码显示了几次内存泄漏。每次您分配一个POINTER时,都需要非常保证将有一个匹配的DEALLOCATE。

您的测试代码中有一个循环。分配器在setter和getter被称为很多匹配的DEALLOCATE语句在哪里?

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章