Anya is live and ready to show you everything. Watch her strip, dance, and perform exclusive shows just for you. Interact in real-time and make your fantasies come true.
✓ Live Streaming✓ Interactive Chat✓ Private Shows✓ HD Quality✓ Free Actions
Free to watch • No registration required • HD streaming
module regex_module use iso_c_binding implicit none type :: regex_type byte, pointer :: buffer(:) type(C_ptr) :: preg end type regex_type type, bind(C) :: regmatch_t integer(c_int64_t) :: rm_so integer(c_int64_t) :: rm_eo end type regmatch_t interface function C_regcomp(reg, pattern, flags) result(status) bind(C,name="regcomp") import type(C_ptr), value :: reg character(len=1,kind=C_char), intent(in) :: pattern(*) integer(c_int), intent(in), value :: flags integer(C_int) :: status end function C_regcomp function C_regexec(reg,string,nmatch,matches,flags) result(status) bind(C,name="regexec") import type(C_ptr), intent(in), value :: reg character(len=1,kind=C_char), intent(in) :: string(*) type(regmatch_t), intent(out) :: matches integer(C_size_t), intent(in), value :: nmatch integer(C_int), intent(in), value :: flags integer(C_int) :: status end function C_regexec function C_regerror(errcode, reg, errbuf, errbuf_size) result(regerror) bind(C,name="regerror") import integer(C_size_t) :: regerror integer(C_int), value :: errcode type(C_ptr), intent(in), value :: reg character(len=1,kind=C_char), intent(out) :: errbuf integer(C_size_t), value :: errbuf_size end function C_regerror subroutine C_regfree(reg) bind(C,name="regfree") import type(C_ptr), intent(in), value :: reg end subroutine C_regfree end interface contains (モジュール関数の実装) end module regex_module
一応確認しますと、例えば
function C_regcomp(reg, pattern, flags) result(status) bind(C,name="regcomp")
exec status = 0 match = T match position 1 start: 0 , end: 9 match position 2 start: 3 , end: 6 match position 3 start: 6 , end: 9 match position 4 start: -1 , end: -1 match position 5 start: -1 , end: -1
もし、対象の文字列を適当に変更してマッチしないようにした場合、
exec status = 1 error message: regexec() failed to match match = F match position 1 start: 6445715608 , end: 0 match position 2 start: 0 , end: 0 (以下略)
module class_c2 use class_c1 implicit none type c2 type(c1) :: c type(c1),allocatable :: a(:) integer :: nlen contains final :: final_c2 end type c2 contains function new_c2(n) result(r) integer,intent(in) :: n type(c2) :: r integer :: i allocate(r%a(n)) do i = 1,n r%a(i) = new_c1(i) enddo r%c = new_c1(n + 1) r%nlen = n end function new_c2 subroutine final_c2(this) type(c2) :: this write(*,*) "final_c2 is called, nlen = ",this%nlen end subroutine final_c2 end module class_c2
program hoge use class_c2 implicit none call test(5) stop contains subroutine test(n) integer,intent(in) :: n type(c2) :: c c = new_c2(n) end subroutine test end program hoge
前略 ==12103== Conditional jump or move depends on uninitialised value(s) ==12103== at 0x4F18284: write_integer (write.c:1050) 中略 ==12103== Conditional jump or move depends on uninitialised value(s) ==12103== at 0x4F1828D: write_integer (write.c:1055) 中略 ==12103== Conditional jump or move depends on uninitialised value(s) ==12103== at 0x4F18433: write_integer (write.c:1064) 中略 ==12103== Conditional jump or move depends on uninitialised value(s) ==12103== at 0x53D45B6: __umodti3 (libgcc2.c:1028) 中略 ==12103== Conditional jump or move depends on uninitialised value(s) ==12103== at 0x53D449E: __udivti3 (libgcc2.c:1028) 中略 ==12103== Conditional jump or move depends on uninitialised value(s) ==12103== at 0x4F182EA: write_integer (write.c:1064) 中略 ==12103== Conditional jump or move depends on uninitialised value(s) ==12103== at 0x4C28F68: strlen (mc_replace_strmem.c:403) 中略 ==12103== Syscall param write(buf) points to uninitialised byte(s) ==12103== at 0x58FD780: __write_nocancel (in /lib64/libc-2.12.so) 中略 ==12103== ==12103== HEAP SUMMARY: ==12103== in use at exit: 0 bytes in 0 blocks ==12103== total heap usage: 36 allocs, 36 frees, 12,346 bytes allocated ==12103== ==12103== All heap blocks were freed -- no leaks are possible ==12103== ==12103== For counts of detected and suppressed errors, rerun with: -v ==12103== Use --track-origins=yes to see where uninitialised values come from ==12103== ERROR SUMMARY: 22 errors from 8 contexts (suppressed: 6 from 6)
module class_c2 use class_c1 implicit none type c2 type(c1),pointer :: p type(c1),allocatable :: a(:) integer :: nlen contains final :: final_c2 end type c2 contains function new_c2(n) result(r) integer,intent(in) :: n type(c2) :: r integer :: i allocate(r%a(n)) allocate(r%p) do i = 1,n r%a(i) = new_c1(i) enddo r%c = new_c1(n + 1) r%nlen = n end function new_c2 subroutine final_c2(this) type(c2) :: this deallocate(this%p) write(*,*) "final_c2 is called, nlen = ",this%nlen end subroutine final_c2 end module class_c2
実行すると。
Finalizer final_c1 called, x length = 6 final_c2 is called, nlen = 5 Finalizer final_c1_array called, x length = 1 Finalizer final_c1_array called, x length = 2 Finalizer final_c1_array called, x length = 3 Finalizer final_c1_array called, x length = 4 Finalizer final_c1_array called, x length = 5
program hoge use class_c1 implicit none type t type(c1) :: c end type t type(t),allocatable :: a(:) integer :: i allocate(a(10)) do i = 1,10 a(i)%c = new_c1(i) enddo deallocate(a) stop end program hoge
これを実行すると
Finalizer final_c1 called, x length = 1 Finalizer final_c1 called, x length = 2 Finalizer final_c1 called, x length = 3 Finalizer final_c1 called, x length = 4 Finalizer final_c1 called, x length = 5 Finalizer final_c1 called, x length = 6 Finalizer final_c1 called, x length = 7 Finalizer final_c1 called, x length = 8 Finalizer final_c1 called, x length = 9 Finalizer final_c1 called, x length = 10
program hoge use class_c1 implicit none type t type(c1) :: c end type t call fuga(20) call blah(3) stop contains subroutine fuga(n) integer,intent(in) :: n type(t) :: p write(*,*) "Subroutine fuga" p%c = new_c1(n) end subroutine fuga subroutine blah(n) integer,intent(in) :: n type(t),allocatable :: p(:) integer :: k write(*,*) "Subroutine blah" allocate(p(n)) do k = 1,n p(k)%c = new_c1(k) enddo end subroutine blah end program hoge
実行するとこんな感じ。
Subroutine fuga Finalizer final_c1 called, x length = 20 Subroutine blah Finalizer final_c1 called, x length = 1 Finalizer final_c1 called, x length = 2 Finalizer final_c1 called, x length = 3
end subroutineに達すると、subroutine内で宣言した構造体が開放され、Finalizerも呼び出されていることが分かります。
注目するべきはblahの中で、deallocateが呼び出されていないのに配列pがdeallocateされてるっぽいことですね。
なんか仕様書にそういう感じのことが書いてあった気がします。つまりend subroutineとかend functionが実行されるとなんかallocateなものはdeallocateされると。
MAY 2004版のFortran2003の仕様書の6.3.3.1節の一節です。
When the execution of a procedure is terminated by execution of a RETURN or END statement, an allocatable variable that is a named local variable of the procedure retains its allocation and definition status if it has the SAVE attribute or is a function result variable or a subobject thereof; otherwise, it is deallocated.
module hoge use class_c1 implicit none type(c1) :: x type(c1),allocatable :: a(:) end module hoge
これらはともに、明示的に開放してやらないといけません。ちゃんとdeallocate(a)とか、xのfinalizerを自分で呼び出しましょう。
COMMON BLOCKにインスタンスがあるときはどうなるかという問題もありますが、正直COMMON BLOCKとは関わりたくないので、ここでは触れません。
次はクラスの中に別のクラスを定義して、その中身にあるクラスのFinalizerのタイミングを調べようと思います。
Anya is live and ready to show you everything. Watch her strip, dance, and perform exclusive shows just for you. Interact in real-time and make your fantasies come true.
✓ Live Streaming✓ Interactive Chat✓ Private Shows✓ HD Quality✓ Free Actions
Free to watch • No registration required • HD streaming
と一行にまとめてしまう感じです。
こう書いたとき、コードには t は現れないですが、プログラム内部的には、どこかに t に相当する空間にsin(x)を一時的に保管する必要があります。
このケースでは実数という組み込み型だからプログラム側で何とかしてくれますが、デストラクタを持つ構造体が一時的に生成される場合、 そのデストラクタはどうなるのでしょうか。
とりあえず、donor関数がc1の一時オブジェクトを提供し、acceptorサブルーチンに渡すという構造を考えます。
c1クラスについては、前回まで
http://sage-t.tumblr.com/post/89280369914/fortran2003-final-procedure-1
http://sage-t.tumblr.com/post/89368816594/fortran2003-final-procedure-2
のものを流用します。
program hoge use class_c1 implicit none call acceptor(donor(3)) stop contains function donor(n) result(r) integer,intent(in) :: n type(c1) :: r r = new_c1(n) r%x(:) = 1.d0 end function donor subroutine acceptor(t) type(c1),intent(in) :: t type(c1) :: c c = new_c1(5) write(*,*)t%x end subroutine acceptor end program hoge
program hoge implicit none integer,allocatable :: x(:) integer :: i x = (/1,2,3,4,5/) write(*,*) x x(:) = (/ (i,i=1,10) /) write(*,*) x x = (/ (i,i=1,10) /) write(*,*) x stop end program hoge
を実行したら
1 2 3 4 5 1 2 3 4 5 *** glibc detected *** ./a.out: realloc(): invalid next size: 0x0000000001e8af80 *** (中略、GCC4.6くらいからデフォルトになったbacktrace出力) Program received signal SIGABRT: Process abort signal. (略)
program hoge implicit none character(:),allocatable :: x do while (x /= "q") x = readStr() call writestr(x) !この2行はcall writestr(readStr())と1行で書けるんですが、while条件文にも使いたかったので。 !ちなみにcall writestr(readStr())としても別にメモリリークは起こりませんでした。 !おそらく関数引数の一時オブジェクトは勝手にdeallocateされる模様。 end do deallocate(x) !readStrの中でallocateされているため。 write(*,*) "Stop" stop contains function readStr() result(str) character(:),allocatable :: str allocate(character(len=256)::str) !allocateしておかないとreadに渡せない。allocateの例を兼ねて。 read(*,*) str str = trim(str) !ここでreallocateが起こっている。 end function readStr subroutine writestr(str) character(len=*) :: str write(*,'(3a,i0)')"string '",str,"' has length ",len(str) end subroutine writestr end program hoge
module class_c1 implicit none type c1 integer :: n double precision,allocatable :: x(:) contains final :: final_c1 final :: final_c1_array end type c1 contains subroutine final_c1(this) type(c1),intent(inout) :: this if(allocated(this%x))deallocate(this%x) write(*,*) "Finalizer final_c1 called, x length = ",this%n end subroutine final_c1 subroutine final_c1_array(this) type(c1),intent(inout) :: this(:) integer :: i do i = lbound(this,1),ubound(this,1) if(allocated(this(i)%x))deallocate(this(i)%x) write(*,*) "Finalizer final_c1_array called, x length = ",this(i)%n enddo end subroutine final_c1_array function new_c1(nlen) result (c) type(c1) :: c integer,intent(in) :: nlen c%n = nlen allocate(c%x(c%n)) end function new_c1 end module class_c1
program hoge use class_c1 implicit none call test(10) write(*,*) "pyonpyon" contains subroutine test(n) integer,intent(in) :: n type(c1) :: c c = new_c1(n) write(*,*) "kokoro pyonpyon" end subroutine test end program hoge
program hoge use class_c1 implicit none type(c1),pointer :: a allocate(a) a = test(10) write(*,*) "-------" deallocate(a) contains function test(n) result(c) integer,intent(in) :: n type(c1) :: c,ct ct = new_c1(n) c = ct end function test end program hoge
program hoge use class_c1 implicit none call test(5) write(*,*) "するんじゃ^~" contains subroutine test(n) integer,intent(in) :: n type(c1) :: c(n) integer :: i do i = 1,n c(i) = new_c1(i) enddo write(*,*) "こころぴょんぴょん" end subroutine test end program hoge
これをsub_test2.f03として、コンパイルと実行してみます。
$ gfortran class_c1.o sub_test2.f03 -o ああ^~ $ ./ああ^~ こころぴょんぴょん Finalizer final_c1_array called, x length = 1 Finalizer final_c1_array called, x length = 2 Finalizer final_c1_array called, x length = 3 Finalizer final_c1_array called, x length = 4 Finalizer final_c1_array called, x length = 5 するんじゃあ^~
と、やはり配列だと配列用のデストラクタが呼び出されています。
END PROGRAMだとこのような呼び出され方はされず、メモリリークが起こっていました。
関数・サブルーチン内では一時的な変数として使われることが多いだろうということで、このような仕様なのでしょうか。
あと確かめていませんが、サブルーチン内でも普通に前回のようなallocate・deallocateペアは使えると思います。
次は、モジュール内とか構造体内のメンバ変数になってたときでも試してみようかな。
とりあえずは関数の戻り値としてのインスタンスをそのまま別の関数に渡してみました。
http://sage-t.tumblr.com/post/89650215774/fortran2003-final-procedure-3