循環参照のはなし
Upcoming SlideShare
Loading in...5
×
 

循環参照のはなし

on

  • 4,067 views

循環参照の見つけ方と直し方の話

循環参照の見つけ方と直し方の話

Statistics

Views

Total Views
4,067
Views on SlideShare
4,048
Embed Views
19

Actions

Likes
5
Downloads
13
Comments
0

2 Embeds 19

http://paper.li 18
https://twitter.com 1

Accessibility

Categories

Upload Details

Uploaded via as Apple Keynote

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • 【5分】\n
  • 【5分】\n
  • 【5分】\n
  • 【5分】\n
  • \n
  • \n
  • \n
  • よい: リークしてるかの判定としては性格、わるい: 原始的、環境依存\n
  • よい: リーク全般を見つけられる、わるい: 結果の表示がごつい\n
  • よい: 結果がみやすい、だめ: 循環参照を探すだけ。XSのリークは検出できない。OUTER絡みも無理ぽ。\n\n
  • よい: 簡単にリーク検出、 わるい: オブジェクト限定\n
  • 【10分】よい: 解放タイミングが正確にわかる(中のクロージャから解放される) わるい: ひどいハック\n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • 【15分】undef エラーの原因となる。この例だとリークする。\n
  • この例だと、weakenよりこちらが自然\n
  • APIを変更し、クロージャを渡さずにすむようにする\n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • 甲斐互換のためにautorelease で返してくることがあるが、それだとうまくいかない。仕様をよく調べる必要あり。\n
  • \n

循環参照のはなし 循環参照のはなし Presentation Transcript

  • 2011.12.10 hiratara
  • d.hatena.ne.jp/hirataratwitter.com/hirataraPerlYAPC gihyo.jp
  • my ($ref1, $ref2, $ref3); $ref1 = $ref2; $ref2 = $ref3; $ref3 = $ref1;$ref1 $ref2 $ref3 View slide
  • GCPerl GC View slide
  • mark-and-sweep GC
  • mark-and-sweep GC
  • mark-and-sweep GC
  • mark-and-sweep GC
  • reference counting 1 11 1 2 1 2 1
  • reference counting 1 01 1 2 1 2 1
  • reference counting 1 01 0 1 1 2 1
  • reference counting 1 01 0 1 1 1 1
  • reference counting 1 01 0 1 Leak 1 1 1
  • (1) Template::Plugin::Filter (TT-2.2) Template::Pluginreturn $self->{ _STATIC_FILTER } ||= sub { $self->filter(shift);};
  • (2) AnyEventmy $t; $t = AE::timer 1, 0, sub { ...; undef $t;}; $t sub { ... }
  • (2) AnyEventmy $t; $t = AE::timer 1, 0, sub { ...; undef $t;}; $t sub { ... }
  • (2) AnyEventmy $t; $t = AE::timer 1, 0, sub { ...; undef $t;}; $t
  • (2) AnyEventmy $t; $t = AE::timer 1, 0, sub { ...; undef $t;}; $t
  • (2) AnyEventmy $t; $t = AE::timer 1, 0, sub { ...; undef $t;};
  • (3)my ($f, $x);(sub { $f = sub { $x } })->(); OUTSIDE sub {...} $f == sub { ... }
  • (3)use Devel::Peek; Dump($f);SV = IV(0x100827fd8) at 0x100827fe0 REFCNT = 2 RV = 0x100827878 SV = PVCV(0x10082b5f8) at 0x100827878 REFCNT = 1 GVGV::GV = 0x100856bc0 "main" :: "__ANON__" OUTSIDE = 0x1008032a0 (ANON) SV = PVCV(0x100852a90) at 0x1008032a0 REFCNT = 1 GVGV::GV = 0x100856bc0 "main" :: "__ANON__" PADNAME = 0x1008277e8(0x100287000) PAD = 0x100827800(0x10025c0e0) 1. 0x100827fe0<2> FAKE "$f" flags=0x0 index=1
  • 5( ≒ )
  • 1) ps% perl for (1 .. 10000) { my $ref; $ref = $ref; warn `ps -o rss= -p $$` if $_ % 1000 == 0; } 1272 1304 1328 1352 1376...
  • 2) Test::LeakTraceuse Test::LeakTrace;no_leaks_ok { my $ref; $ref = $ref };
  • 2) Test::LeakTraceuse Test::LeakTrace;no_leaks_ok { my $ref; $ref = $ref }; not ok 1 - leaks 1 <= 0 # Failed test leaks 1 <= 0 # at - line 4. # 1 # <= # 0 # leaked REF(0x10083b610) from - line 4. # SV = IV(0x10083b608) at 0x10083b610 # REFCNT = 1 # FLAGS = (PADMY,ROK) # RV = 0x10083b610 # SV = IV(0x10083b608) at 0x10083b610 # REFCNT = 1 # FLAGS = (PADMY,ROK) # RV = 0x10083b610 # SV = IV(0x10083b608) at 0x10083b610 # REFCNT = 1 # FLAGS = (PADMY,ROK) # RV = 0x10083b610 # SV = IV(0x10083b608) at 0x10083b610 ...
  • 3) Devel::Cycleuse Devel::Cycle;my ($ref1, $ref2, $ref3);$ref1 = $ref2;$ref2 = sub { $ref3 };$ref3 = [$ref1];find_cycle($ref1);Cycle (1): $$A => &B $B variable $ref3 => $C $$C => @D $D->[0] => $A
  • 4) Devel::Leak::Objectuse Devel::Leak::Object qw{GLOBAL_bless};$Devel::Leak::Object::TRACKSOURCELINES = 1;my $ref; $ref = bless $ref => "XXX";Tracked objects by class: XXX 1Sources of leaks:XXX 1 from - line: 3
  • 5) DESTROYsub Ref1::DESTROY { warn "destroyed REF1" }sub Ref2::DESTROY { warn "destroyed REF2" }my $x;my $f = bless sub { $x; bless sub { $x } => "Ref2";} => "Ref1";$f->();destroyed REF2 at - line 2.destroyed REF1 at - line 1.
  • Devel::GladiatorPASS (181) FAIL (436)
  • 5
  • $self sub { ... }
  • my $self = {name => "Hokkaido.pm", handler => undef};$self->{handler} = sub { print "Hello, ", $self->{name}, ".n";};$self->{handler}->(); sub { ... } $self “Hokkaido.pm”
  • 1)my $self = {name => "Hokkaido.pm", handler => undef};$self->{handler} = sub { print "Hello, ", $self->{name}, ".n"; undef $self;};$self->{handler}->(); sub { ... } $self “Hokkaido.pm”
  • 1)my $self = {name => "Hokkaido.pm", handler => undef};$self->{handler} = sub { print "Hello, ", $self->{name}, ".n"; undef $self;};$self->{handler}->(); sub { ... } $self “Hokkaido.pm”
  • 1)my $self = {name => "Hokkaido.pm", handler => undef};$self->{handler} = sub { print "Hello, ", $self->{name}, ".n"; undef $self;};$self->{handler}->(); sub { ... } “Hokkaido.pm”
  • 1)my $self = {name => "Hokkaido.pm", handler => undef};$self->{handler} = sub { print "Hello, ", $self->{name}, ".n"; undef $self;};$self->{handler}->(); sub { ... } “Hokkaido.pm”
  • 1)my $self = {name => "Hokkaido.pm", handler => undef};$self->{handler} = sub { print "Hello, ", $self->{name}, ".n"; undef $self;};$self->{handler}->();
  • 1)( )($self->{handler} )
  • 2) Scalar::Util::weakenmy $self = {name => "Hokkaido.pm", handler => undef};Scalar::Util::weaken(my $weaken_self = $self);$self->{handler} = sub { print "Hello, ", $weaken_self->{name}, ".n";};$self->{handler}->(); sub { ... } $self “Hokkaido.pm”
  • 2) Scalar::Util::weakenmy $self = {name => "Hokkaido.pm", handler => undef};Scalar::Util::weaken($self); #$self->{handler} = sub { print "Hello, ", $self->{name}, ".n";};$self->{handler}->();
  • 3)my $self = {name => "Hokkaido.pm", handler => undef};my $name = $self->{name};$self->{handler} = sub { print "Hello, ", $name, ".n";};$self->{handler}->(); sub { ... } $self “Hokkaido.pm”
  • 4)my $self = {name => "Hokkaido.pm", handler => undef};$self->{handler} = sub { my $self = shift; print "Hello, ", $self->{name}, ".n";};$self->{handler}->($self); sub { ... } $self “Hokkaido.pm”
  • 4)AnyEvent::Handler $hdl->push_read (line => sub { my ($hdl, $line) = @_; ... });
  • 5) Data::Decycleuse Data::Decycle;my $guard = Data::Decycle->new( my $self = {name => "Hokkaido.pm", handler => undef});$self->{handler} = sub { "Hello, ", $self->{name}, ".n";};$self->{handler}->();
  • 5) Data::Decycledankogai guard 1)
  • :Perl 5.8.8use Devel::Leak::Object qw{GLOBAL_bless};bless my $x = {}, "Dummy";(sub { sub { $x } })->();Tracked objects by class: Dummy 1
  • :Perl 5.8.8my $x = bless {}, "Dummy";(sub { $x; sub { $x } })->();my $x = bless {}, "Dummy";(sub { my $x = $x; sub { warn $x } })->();
  • :Obj-C ARCretain release PerlCBRFuture *future = [[CBRFuture alloc] init];__weak CBRFuture *weakenFuture = future;leftHandle(self, ^(id e) { current = nil; leftSend(weakenFuture, e);});
  • :Obj-C GuardNSString *local = @"OK";static void changeLocalValue(BOOL willBreak) { id original = local; CBRGuard *guard = [[CBRGuard alloc] initGuard:^{ local = original; }]; local = @"LOCALVALUE1";}
  • :Obj-C Guard autorelease