Skip Menu |

This queue is for tickets about the Net-SDP CPAN distribution.

Report information
The Basics
Id: 8019
Status: resolved
Priority: 0/
Queue: Net-SDP

People
Owner: njh [...] cpan.org
Requestors:
Cc:
AdminCc:

Bug Information
Severity: Important
Broken in: 0.01
Fixed in: (no value)



Subject: Circular references causing memory leaks
Hi. You've got a few circular references in your code, and a few memory leaks as a result. For example: my $media = Net::SDP::Media->_new( $self, $value ); ... push( @{$self->{'media'}}, $media ); You store a reference to a Net::SDP::Media object in the Net::SDP object, but you also store a reference to the Net::SDP object in the Net::SDP::Media object. Circular reference. Neither object gets destroyed because both contain references to one another. Here: for (1..300000) { my %hash_one = ( foo => 7, bar => 8, hash_two => undef ); my %hash_two = ( baz => 15, hash_one => \%hash_one ); $hash_one{hash_two} = \%hash_two; } print "Done.\n"; Run that code and watch it hang at the end. The hashes don't get cleaned up after each iteration of the loop because their reference counts never dropped below zero. It's only at the very end when Perl does global destruction that they get cleaned up, all 500,000 of them at once. Comment out this line: $hash_one{hash_two} = \%hash_two; and see the difference. Here's an article on all of this: http://www.perl.com/pub/a/2002/08/07/proxyobject.html Basically, %parent can contain references to %child, but not %child cannot contain any references to %parent. I know, this sucks, but it's either that or leak memory.
From: Nicholas Humfrey
I have removed the references to session in Net::SDP::Time and Net::SDP::Media. There were for future use anyway. Thanks for the bug report. nick. [guest - Thu Oct 14 23:53:55 2004]: Show quoted text
> Hi. > > You've got a few circular references in your code, and a few memory > leaks as a result. > > For example: > > my $media = Net::SDP::Media->_new( $self, $value ); > ... > push( @{$self->{'media'}}, $media ); > > You store a reference to a Net::SDP::Media object in the Net::SDP > object, but you also store a reference to the Net::SDP object in > the Net::SDP::Media object. Circular reference. Neither object gets > destroyed because both contain references to one another. Here: > > for (1..300000) { > my %hash_one = ( > foo => 7, > bar => 8, > hash_two => undef > ); > > my %hash_two = ( > baz => 15, > hash_one => \%hash_one > ); > > $hash_one{hash_two} = \%hash_two; > } > > print "Done.\n"; > > Run that code and watch it hang at the end. The hashes don't get > cleaned up after each iteration of the loop because their reference > counts never dropped below zero. It's only at the very end when > Perl does global destruction that they get cleaned up, all 500,000 > of them at once. > > Comment out this line: > > $hash_one{hash_two} = \%hash_two; > > and see the difference. > > Here's an article on all of this: > http://www.perl.com/pub/a/2002/08/07/proxyobject.html > > Basically, %parent can contain references to %child, but not %child > cannot contain any references to %parent. I know, this sucks, but > it's either that or leak memory.