Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
0
Help us understand the problem. What is going on with this article?
@cometscome_phys

Fortranでメモリリーク?-どこまでも増えていくメモリ使用量(原因不明)

オブジェクト指向Fortranを使ってコードを書いていたら、使用メモリ量がどんどん増えていくバグに遭遇しました。deallocateしているはずなのにどんどん増えていきます。

問題のコード

コードはこんな感じです。

program main
    use test
    implicit none
    integer::N

    complex(8),allocatable::vec_data(:)

    N = 100000

    allocate(vec_data(N))

    vec_data = pmap(N,wrap)

    contains 

    function wrap(i)
        integer,intent(in)::i
        complex(8)::wrap
        type(type_test),allocatable::testdata
        allocate(testdata)
        testdata = type_test(N)
        wrap = 0d0
        deallocate(testdata)
    end function

end program 

ここで、type_testというクラスはmodule testで定義されており、

module test
    implicit none

    type type_test
        class(type_inner),allocatable::vec
    end type

    interface type_test
        module procedure::init_test
    end interface

    type type_inner
        complex(8),allocatable::x(:)
    end type

    interface type_inner
        module procedure::init_inner
    end interface

    contains 

    type(type_test) function init_test(N) result(testdata)
        integer::N
        allocate(testdata%vec)
        testdata%vec = init_inner(N) 
    end function

    type(type_inner) function init_inner(N) result(vec)
        integer::N,i
        allocate(vec%x(1:N))
        do i=1,N
            vec%x(i) = i
        end do
    end function

    function pmap(N,func) result(vec_data)
        interface 
            function func(i)
                integer,intent(in)::i
                complex(8)::func
            end function
        end interface
        integer,intent(in)::N
        integer::i
        complex(8)::v
        complex(8)::vec_data(N)

        do i=1,N
            vec_data(i) = func(i)
        end do

    end function

end module

です。フィールドにtype_innerというクラスを持ち、そのクラスの中で配列が確保されています。ですので、構造体のフィールドに構造体がありそのフィールドに配列、というものを用意しています。

結果

moduleを上に、mainを下に書いてgfortranでコンパイルして実行すると、なぜか使用メモリが増えていきます。deallocate(testdata)しているのに、メモリが増えていきます。

  • Mac OS 10.14および10.15
  • gfortran 9と10

で確認しました。

原因は不明です。

追記

@cure_honeyさんのコメントの通り、

    type(type_test) function init_test(N) result(testdata)
        integer::N
        type(type_inner) :: dummy

        dummy = init_inner(n)
        testdata%vec = dummy
    end function

とすることでメモリーリークが消えることが確認できました。

@implicit_none さんの提案のfinalizer処理の追加

    type type_test
        class(type_inner),allocatable::vec

        contains
        final :: vec_final ! finalizer
    end type

    subroutine vec_final(this)
        use, intrinsic :: iso_fortran_env
        implicit none
        type(type_test) :: this ! not "class"

        if (allocated(this%vec)) deallocate (this%vec)
    end subroutine vec_final

をやってみましたが、問題は解決できませんでした。deallocateを明示的に書いてもやってくれないのは、@cure_honeyさんのおっしゃるclassの具体形がわからないからでしょうか...

0
Help us understand the problem. What is going on with this article?
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
cometscome_phys
Fortran90、Python、Juliaを使う物性理論な人

Comments

No comments
Sign up for free and join this conversation.
Sign Up
If you already have a Qiita account Login
0
Help us understand the problem. What is going on with this article?