在Fortran中复制复杂派生类型的正确方法

时间:2017-03-15 17:58:40

标签: pointers memory-leaks fortran

我在Visual Studio 2012中使用了英特尔Visual Fortran 2015。

我已经尝试了许多不同的方法来尝试在我的代码中创建一个复杂的派生类型的副本,并且我能想到的每一种方式都会导致内存泄漏,所以我一定做错了。

以下是我的问题的简化示例

type Vehicle_T

    real :: time
    real, dimension(3) :: eciPos
    ...
    a bunch of variables
    ...

end Type Vehicle_T

type, extends(Vehicle_Entity_T) :: Aircraft_T
    real :: alt
    ...
    a bunch of variables
    ...
end type Aircraft_T


type Track_T
    real :: tupdated
    ...
    a bunch of variables
    ...

    class(Vehicle_T), pointer :: object

end type Track_T

type(Track_T) :: a, b

a = constructTrack(various values)

b = copyTrack(a)

contains

!The simplest way I've found that works but causes memory leak
function copyTrack(inTrack) result(outTrack)

    type(Track_T), intent(in) :: inTrack
    type(Track_T) :: outTrack

    outTrack = inTrack
    allocate(outTrack%object, source = inTrack%object)

end function copyTrack

!Another method that causes a memory leak
function copyTrack2(inTrack) result(outTrack)

    type(Track_T), intent(in) :: inTrack
    type(Track_T) :: outTrack

    outTrack%tupdated = inTrack%tupdated
    ...copy all of the rest of the values...

    if(associated(outTrack%object)) deallocate(outTrack%object)
    allocate(outTrack%object, source = inTrack%object)

end function copyTrack2

1 个答案:

答案 0 :(得分:2)

执行

时,您必须处理IF (Test-Path -Path $destinationDirectory -PathType Container) { Write-Host "$destinationDirectory already exists" -ForegroundColor Red } ELSE { New-Item -Path $destinationDirectory -ItemType directory } Get-ChildItem $sourceDirectory -Include $includeFiles -Exclude $excludeFiles -Recurse -Force | New-Item -ItemType File -Path { Join-Path $destinationDirectory $_.FullName.Substring($sourceDirectory.Length) } -Force Get-ChildItem $sourceDirectory -Include $includeFiles -Exclude $excludeFiles -Recurse -Force | Copy-Item -Destination { Join-Path $destinationDirectory $_.FullName.Substring($sourceDirectory.Length) } 组件object
b

新对象的来源。 无论你在你的功能中做什么,它总是会泄漏。(或者,如果你使用finalization,请参见下文。我还没有使用它,因为许多编译器不完全支持它,主要是gfortran 。)

泄漏的原因是`b` = some_new_object 包含一个指针组件,只能从b访问。在内在赋值期间指针将被覆盖,指针的目标将丢失。

使用子程序:

b

或者更好的重载任务:

implicit none

type Vehicle_T

    real :: time = 0
    real, dimension(3) :: eciPos = 0


end Type Vehicle_T

type, extends(Vehicle_T) :: Aircraft_T
    real :: alt

end type Aircraft_T


type Track_T
    real :: tupdated

    class(Vehicle_T), pointer :: object => null()

end type Track_T

type(Track_T) :: a, b

integer :: i

allocate(Aircraft_T :: a%object)

do i = 1, 10
  call copyTrack(b, a)
end do

deallocate(a%object)
deallocate(b%object)

contains


subroutine copyTrack(outTrack, inTrack)

    type(Track_T), intent(in) :: inTrack
    type(Track_T) :: outTrack

    if (associated(outTrack%object)) deallocate(outTrack%object)
    outTrack = inTrack
    allocate(outTrack%object, source = inTrack%object)

end subroutine copyTrack



end

使用功能和完成。 希望不会在ifort中泄漏,但会在gfortran中泄漏。

module types
  implicit none

  type Vehicle_T

      real :: time = 0
      real, dimension(3) :: eciPos = 0


  end Type Vehicle_T

  type, extends(Vehicle_T) :: Aircraft_T
      real :: alt

  end type Aircraft_T


  type Track_T
      real :: tupdated

      class(Vehicle_T), pointer :: object => null()
  contains
      procedure :: copyTrack
      generic :: assignment(=) => copyTrack
  end type Track_T

contains

    subroutine copyTrack(outTrack, inTrack)

        type(Track_T), intent(in) :: inTrack
        class(Track_T), intent(inout) :: outTrack

        if (associated(outTrack%object)) deallocate(outTrack%object)

        allocate(outTrack%object, source = inTrack%object)

    end subroutine copyTrack



end module


  use types

  implicit none

  type(Track_T) :: a, b

  integer :: i

  allocate(Aircraft_T :: a%object)

  do i = 1, 10
    b = a
  end do

  deallocate(a%object)
  deallocate(b%object)

end