Inline::Cで学ぶperlguts(その5)

いろいろ納得いかなかったので、さらに調べてみた。

use v5.14;
use strict;
use warnings;

use Data::Dumper;

use Inline C => q{
    #include <stdio.h>

    SV * func()
    {
        SV *ret = newAV();
        printf( "SvREFCNT(ret) = %d\n", SvREFCNT(ret) );

        SV *tmp = newSViv( 123 );
        printf( "brefore push : SvREFCNT(tmp) = %d\n", SvREFCNT(tmp) );

        av_push( ret, tmp );
        printf( "  after push : SvREFCNT(tmp) = %d\n", SvREFCNT(tmp) );

        return newRV_noinc( (SV *)ret );
    }
};

my $foo = func();
say Dumper($foo);

$ perl aaa.pl
SvREFCNT(ret) = 1
brefore push : SvREFCNT(tmp) = 1
after push : SvREFCNT(tmp) = 1
$VAR1 = [
123
];

そもそも、av_pushしても参照カウントが増えないのは、
いつぞやに調べてたのに忘れてた。

あと、配列リファレンス無名配列の違いがよく分かってなかったんだけど、
確かに違うけど、それは気にしないで良さそうってところまで理解した。

次に、メモリリークしているか調べる方法については、
undefすれば即時メモリを解放するらしいので、
以下のようなスクリプトを書いて、
Macならアクティビティモニタを見ることで確認できる。(*1)

use v5.14;
use strict;
use warnings;

use Inline C => q{
    #include <stdio.h>

    SV * allocate_large_memory()
    {
        SV *ret = newAV();
        av_fill( ret, (1024 * 1024 * 32) - 1 );
        return newRV_noinc( (SV *)ret );
    }

    SV * func()
    {
        SV *ret = newAV();
        printf( "SvREFCNT(ret) = %d\n", SvREFCNT(ret) );

        SV *tmp = allocate_large_memory();
        printf( "brefore push : SvREFCNT(tmp) = %d\n", SvREFCNT(tmp) );

        av_push( ret, tmp );
        printf( "  after push : SvREFCNT(tmp) = %d\n", SvREFCNT(tmp) );

        return newRV_noinc( (SV *)ret );
    }
};

my $foo = func();
say scalar(@{$foo->[0]});
foreach ( 1..5 ) {
    say $_;
    sleep 1;
}

undef $foo;

foreach ( 1..5 ) {
    say $_;
    sleep 1;
}

$ perl bbb.pl
SvREFCNT(ret) = 1
brefore push : SvREFCNT(tmp) = 1
after push : SvREFCNT(tmp) = 1
16777216
1
2
3
4
5
1
2
3
4
5

最初の5秒間は、アクティビティモニタのメモリタブでperlが上位に来ると思う。
次の5秒間は、perlが上位から消える。

こんな感じで、メモリリークしているか確かめる方法が分かったので、
不安になったらこの方法で確かめていこうと思う。

今回は、こちらを参考にさせていただきました。

Perlでのメモリ開放について – skozawa’s blog
http://skozawa.hatenablog.com/entry/2013/02/18/235021

おしまい。

(*1) メニューの[表示]-[更新の頻度]で「非常に多く(1秒ごと)」を選んでおくこと

Leave a Comment