Fortran 90函数返回指针 [英] Fortran 90 function return pointer

查看:212
本文介绍了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 =形状(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))... 开始,那么你的代码可能是合理的。

但是...


  • if this% TF3D 为true,那么此%vals3D 必须关联。
  • 函数,您必须使用指针赋值

      array_ptr => getValues3D(foo)
    ! ^
    ! |
    ! +这个小角色非常重要。

    忘记那个小角色,你正在使用正常的赋值。在读取代码时,语法上有效,很难挑出差异,在这种情况下,除了使用指针的常见缺陷之外(例如,您需要DEALLOCATE),在可能最糟糕的时刻之前可能未检测到内存损坏或泄漏的来源array_ptr在重用之前或超出范围)。这就是为什么返回指针结果的函数被认为是有风险的。







    $ b <你的完整代码显示了几个内存泄漏。每次你分配一个POINTER的东西时 - 你需要保证会有一个匹配的DEALLOCATE。



    你的测试代码中有一个循环。 ALLOCATE被调用了很多 - 在 setter和getter中。匹配的DEALLOCATE语句在哪里?


    I saw this question:

    Fortran dynamic objects

    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, then this%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函数返回指针的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆