develooper Front page | perl.perl5.porters | Postings from June 2009

Re: DESTROY: is there any predictability about when it's called?

Thread Previous | Thread Next
From:
demerphq
Date:
June 14, 2009 03:04
Subject:
Re: DESTROY: is there any predictability about when it's called?
Message ID:
9b18b3110906140303y1fc5f6e4q46d1c0403c71618f@mail.gmail.com
2009/6/14 demerphq <demerphq@gmail.com>:
> 2009/6/13 Andy Armstrong <andy@hexten.net>:
>> I'm writing some code that catches memory leaks:
>>
>> leakguard {
>>  # do something that leaks
>> };
>>
>> If there are any object leaks inside the block it should warn at exit. The
>> leakguard sub looks like this:
>>
>> sub leakguard(&@) {
>>  my $block = shift;
>>  my $state = My::Mem::State->new( @_ );
>>  my $rc    = $block->();
>>  my ( undef ) = ( $state );
>>  return $rc;
>> }
>>
>> My::Mem::State checks for leaked blessed objects when its DESTROY method is
>> called. The problem is that it gets false positives from objects allocated
>> inside $block for which DESTROY is pending but get DESTROYed /after/ the
>> My::Mem::State.
>>
>> On 5.10 the my ( undef ) = ( $state ) seems to work to force $state to be
>> destroyed late enough to avoid false positives - but that's a bit heuristic
>> for my tastes. Is there a reliable way to flush pending DESTROYs or some
>> other way to guarantee that $state is lives longer than anything allocated
>> by $block?
>
> I dont really understand this code. The correct way to tell perl to
> free memory in a block is to explicitly undef the variable.
>
> Also, you have to be careful with the term "leak" in perl.
>
> You see, perl trades memory for speed pretty much always. So for
> instance check this:
>
> demerphq@gemini:~$ perl -MDevel::Peek -e'for (reverse 1..10) { my $x;
> warn "len: ", defined $x ? length($x): "undef","\n"; Dump($x); $x="x"
> x $_; }'
> len: undef
> SV = NULL(0x0) at 0x8153cdc
>  REFCNT = 1
>  FLAGS = (PADBUSY,PADMY)
> len: undef
> SV = PV(0x8154ae8) at 0x8153cdc
>  REFCNT = 1
>  FLAGS = (PADBUSY,PADMY)
>  PV = 0x8176b78 "xxxxxxxxxx"\0
>  CUR = 10
>  LEN = 12
> len: undef
> SV = PV(0x8154ae8) at 0x8153cdc
>  REFCNT = 1
>  FLAGS = (PADBUSY,PADMY)
>  PV = 0x8176b78 "xxxxxxxxx"\0
>  CUR = 9
>  LEN = 12
> len: undef
> SV = PV(0x8154ae8) at 0x8153cdc
>  REFCNT = 1
>  FLAGS = (PADBUSY,PADMY)
>  PV = 0x8176b78 "xxxxxxxx"\0
>  CUR = 8
>  LEN = 12
> len: undef
> SV = PV(0x8154ae8) at 0x8153cdc
>  REFCNT = 1
>  FLAGS = (PADBUSY,PADMY)
>  PV = 0x8176b78 "xxxxxxx"\0
>  CUR = 7
>  LEN = 12
> len: undef
> SV = PV(0x8154ae8) at 0x8153cdc
>  REFCNT = 1
>  FLAGS = (PADBUSY,PADMY)
>  PV = 0x8176b78 "xxxxxx"\0
>  CUR = 6
>  LEN = 12
> len: undef
> SV = PV(0x8154ae8) at 0x8153cdc
>  REFCNT = 1
>  FLAGS = (PADBUSY,PADMY)
>  PV = 0x8176b78 "xxxxx"\0
>  CUR = 5
>  LEN = 12
> len: undef
> SV = PV(0x8154ae8) at 0x8153cdc
>  REFCNT = 1
>  FLAGS = (PADBUSY,PADMY)
>  PV = 0x8176b78 "xxxx"\0
>  CUR = 4
>  LEN = 12
> len: undef
> SV = PV(0x8154ae8) at 0x8153cdc
>  REFCNT = 1
>  FLAGS = (PADBUSY,PADMY)
>  PV = 0x8176b78 "xxx"\0
>  CUR = 3
>  LEN = 12
> len: undef
> SV = PV(0x8154ae8) at 0x8153cdc
>  REFCNT = 1
>  FLAGS = (PADBUSY,PADMY)
>  PV = 0x8176b78 "xx"\0
>  CUR = 2
>  LEN = 12
> demerphq@gemini:~$ perl -MDevel::Peek -e'for (1..10) { my $x; warn
> "len: ", defined $x ? length($x): "undef","\n"; Dump($x); $x="x" x $_;
> }'
> len: undef
> SV = NULL(0x0) at 0x81546c0
>  REFCNT = 1
>  FLAGS = (PADBUSY,PADMY)
> len: undef
> SV = PV(0x8154ae8) at 0x81546c0
>  REFCNT = 1
>  FLAGS = (PADBUSY,PADMY)
>  PV = 0x8177c30 "x"\0
>  CUR = 1
>  LEN = 4
> len: undef
> SV = PV(0x8154ae8) at 0x81546c0
>  REFCNT = 1
>  FLAGS = (PADBUSY,PADMY)
>  PV = 0x8177c30 "xx"\0
>  CUR = 2
>  LEN = 4
> len: undef
> SV = PV(0x8154ae8) at 0x81546c0
>  REFCNT = 1
>  FLAGS = (PADBUSY,PADMY)
>  PV = 0x8177c30 "xxx"\0
>  CUR = 3
>  LEN = 4
> len: undef
> SV = PV(0x8154ae8) at 0x81546c0
>  REFCNT = 1
>  FLAGS = (PADBUSY,PADMY)
>  PV = 0x8177c30 "xxxx"\0
>  CUR = 4
>  LEN = 8
> len: undef
> SV = PV(0x8154ae8) at 0x81546c0
>  REFCNT = 1
>  FLAGS = (PADBUSY,PADMY)
>  PV = 0x8177c30 "xxxxx"\0
>  CUR = 5
>  LEN = 8
> len: undef
> SV = PV(0x8154ae8) at 0x81546c0
>  REFCNT = 1
>  FLAGS = (PADBUSY,PADMY)
>  PV = 0x8177c30 "xxxxxx"\0
>  CUR = 6
>  LEN = 8
> len: undef
> SV = PV(0x8154ae8) at 0x81546c0
>  REFCNT = 1
>  FLAGS = (PADBUSY,PADMY)
>  PV = 0x8177c30 "xxxxxxx"\0
>  CUR = 7
>  LEN = 8
> len: undef
> SV = PV(0x8154ae8) at 0x81546c0
>  REFCNT = 1
>  FLAGS = (PADBUSY,PADMY)
>  PV = 0x8177c30 "xxxxxxxx"\0
>  CUR = 8
>  LEN = 12
> len: undef
> SV = PV(0x8154ae8) at 0x81546c0
>  REFCNT = 1
>  FLAGS = (PADBUSY,PADMY)
>  PV = 0x8177c30 "xxxxxxxxx"\0
>  CUR = 9
>  LEN = 12
>
>
> Notice that the memory in the first one "grows" with each iteration,

I meant second here obviously. Sorry for any confusion.


> and is not freed at the end of the loop. The reverse makes this much
> clearer and explains why. See, perl doesnt bother freeing the pv, it
> just modifies it. This avoids calling realloc/malloc all the time, and
> is a desirable optimisation. It also means that this code would appear
> to "leak", except its not leaking as leaking implies losing memory
> unintentionally, and this is a most deliberate optimisation.
>
> However this also often bites people who are only thinking about
> memory profile and not speed as well. So for instance if that var
> ended up being several MB then those MB would appear to "leak".
>
> So be careful with using base memory footprint as a measure of
> "leaked" memory. Its not a leak, its a deliberate optimisation.  To me
> there are two forms of leaked memory in perl. C level, which you need
> to use C level tools sets to find, (like valgrind), and refcycle
> leaks, which are a Hard Problem and probably have to be attacked
> either with a debug mode perl or with code analysis.
>
> Forgive me if you knew this. And i guess you did say "leaked blessed
> objects" but i dont know what you mean by that except for reference
> cycles, and well in that case DESTROY gets called at perl destruction,
> and isnt going to be relevent to your question.... (er, i think).
>
> Maybe i should have drunk more coffee before wrtiting this....
> mea-culpa in advance.
>
> Yves
>
>
>
> --
> perl -Mre=debug -e "/just|another|perl|hacker/"
>



-- 
perl -Mre=debug -e "/just|another|perl|hacker/"

Thread Previous | Thread Next


nntp.perl.org: Perl Programming lists via nntp and http.
Comments to Ask Bjørn Hansen at ask@perl.org | Group listing | About