Skip Menu |

This queue is for tickets about the Class-BuildMethods CPAN distribution.

Report information
The Basics
Id: 23852
Status: resolved
Priority: 0/
Queue: Class-BuildMethods

People
Owner: Nobody in particular
Requestors: collin [...] cpan.org
Cc:
AdminCc:

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



Subject: C::BM does not destroy data from inherited accessors
The cleanup machinery in Class::BuildMethods does not deal with classes that inherit Class::BuildMethods-based accessors from their parents. This results in situations like this: # A inherits the b() accessor from a parent class { my $a = A->new(); $a->b(5); } # $a has gone away { my $a = A->new(); print $a->b; # prints 5 } Because the new $a received the same address as the old $a and because A's DESTROY machinery does not wipe the value store for A's parent classes, $a->b appears to stick around.
Subject: Re: [rt.cpan.org #23852] C::BM does not destroy data from inherited accessors
Date: Fri, 8 Dec 2006 02:14:30 -0800 (PST)
To: bug-Class-BuildMethods [...] rt.cpan.org
From: Ovid <curtis_ovid_poe [...] yahoo.com>
Thanks for the but report. I'll take a look at this tomorrow. Cheers, Ovid --- Collin Winter via RT <bug-Class-BuildMethods@rt.cpan.org> wrote: Show quoted text
> > Thu Dec 07 23:36:20 2006: Request 23852 was acted upon. > Transaction: Ticket created by COLLIN > Queue: Class-BuildMethods > Subject: C::BM does not destroy data from inherited accessors > Broken in: 0.20 > Severity: Important > Owner: Nobody > Requestors: collin@cpan.org > Status: new > Ticket <URL: http://rt.cpan.org/Ticket/Display.html?id=23852 > > > > The cleanup machinery in Class::BuildMethods does not deal with > classes > that inherit Class::BuildMethods-based accessors from their parents. > This results in situations like this: > > # A inherits the b() accessor from a parent class > { > my $a = A->new(); > $a->b(5); > } > # $a has gone away > > { > my $a = A->new(); > print $a->b; # prints 5 > } > > Because the new $a received the same address as the old $a and > because > A's DESTROY machinery does not wipe the value store for A's parent > classes, $a->b appears to stick around. >
-- Buy the book -- http://www.oreilly.com/catalog/perlhks/ Perl and CGI -- http://users.easystreet.com/ovid/cgi_course/
From: OVID [...] cpan.org
On Thu Dec 07 23:36:20 2006, COLLIN wrote: Show quoted text
> The cleanup machinery in Class::BuildMethods does not deal with classes > that inherit Class::BuildMethods-based accessors from their parents. > This results in situations like this: > > # A inherits the b() accessor from a parent class > { > my $a = A->new(); > $a->b(5); > } > # $a has gone away > > { > my $a = A->new(); > print $a->b; # prints 5 > } > > Because the new $a received the same address as the old $a and because > A's DESTROY machinery does not wipe the value store for A's parent > classes, $a->b appears to stick around.
Collin, I'm trying to replicate this and the problem I've found is that I can only replicate this with class data. However, DESTROY only works with an instance, not classes and I can't remove that class data when an instance of a class goes out of scope because that would break all other instances. For example: { package Universe; use Class::BuildMethods pi => { class_data => 1 }; sub new { bless {}, shift } package Other::Universe; use base 'Universe'; } package main; my $u1 = Other::Universe->new; my $u2 = Other::Universe->new; $u1->pi(3.1415); undef $u1; # DESTROY should be triggered my $u3 = Other::Universe->new; print $u2->pi; # should print 3.1415 print $u3->pi; # should print 3.1415 That's an example of how wiping out class data on DESTROY would be bad. If this happens on instance data or if I have misunderstood the problem, please send me a complete code sample and I can look into this. Cheers, Ovid
From: collin [...] cpan.org
Ovid, Sorry, that first example was rather poor. Here's a better one: First, add something like this to Class::BuildMethods: sub get_value_for { return \%value_for; } Next, run this code using the now-modified version of Class::BuildMethods: use strict; use warnings; { package Foo; use Class::BuildMethods qw(a); package Bar; use base qw(Foo); use Class::BuildMethods qw(b); sub new { bless {}, shift(); } } use Class::BuildMethods; { my $b = Bar->new(); $b->a(5); $b->b(6); } use Data::Dumper; print Dumper(Class::BuildMethods::get_value_for()); On my machine, that prints something like $VAR1 = { 'Bar::b' => {}, 'Foo::a' => { '135463296' => 5 } } Here, you can clearly see that $b's instance data for Foo::a is still around. If, by some stroke of bad luck, you create another instance of either Foo or Bar with the same address as $b, that new instance will have Foo::a already filled out. Hope this is a better explanation, Collin Winter
Hi Collin, I've just uploaded 0.22 and hopefully this solves your problem. Thanks for the bug report. A version of your code is now in t/30-regression.t. Please don't reply directly to this email or else RT will automatically reopen this ticket :/ Of course, if the fix doesn't work, then do reply directly :) Cheers, Ovid