Beefy Boxes and Bandwidth Generously Provided by pair Networks
"be consistent"

DESTROY and AUTOLOAD in 5.20.1

by szabgab (Priest)
on Apr 24, 2015 at 09:36 UTC ( [id://1124504] : perlquestion . print w/replies, xml ) Need Help??

szabgab has asked for the wisdom of the Perl Monks concerning the following question:

Given this script:
use strict; use warnings; use 5.010; use Greeting; say 'Hi'; { my $g = Greeting->new; } say 'Bye';
and this module:
package Greeting; use strict; use warnings; use 5.010; use Data::Dumper; sub new { my ($class) = @_; return bless {}, $class; } sub AUTOLOAD { our $AUTOLOAD; say $AUTOLOAD; } DESTROY { say 'destroy'; } 1;
I can see the word "destroy" printed as I would expect. However, if I remove the DESTROY from the module I don't see AUTOLOAD being called instead of the missing DESTROY. I only checked it with 5.20.1 but I wonder what am I missing here?


Reported with perlbug as RT #124387

Replies are listed 'Best First'.
Re: DESTROY and AUTOLOAD in 5.20.1
by kcott (Archbishop) on Apr 24, 2015 at 10:37 UTC

    G'day szabgab,

    [I'm assuming a copy/paste typo: s/DESTROY/sub DESTROY/]

    My reading of perlobj - Destructors, suggests that &DESTROY is only invoked if it has been defined (for instance, there's no default &UNIVERSAL::DESTROY). In particular, the second paragraph:

    "If you want to do something when the object is destroyed, you can define a DESTROY method in your class. This method will always be called by Perl at the appropriate time, unless the method is empty."

    So, if &DESTROY isn't called, &AUTOLOAD won't come into play.

    -- Ken

      sub or no sub, that does not matter for these functions, but I should be more consistent in my example. I think the documentation you linked to says that AUTOLOAD will be called if it exists and DESTROY does not and this was the old behavior.
Re: DESTROY and AUTOLOAD in 5.20.1
by choroba (Cardinal) on Apr 24, 2015 at 10:02 UTC
    In 5.14.4, Greeting::DESTROY is printed. Very weird.
    لսႽ ᥲᥒ⚪⟊Ⴙᘓᖇ Ꮅᘓᖇ⎱ Ⴙᥲ𝇋ƙᘓᖇ
Re: DESTROY and AUTOLOAD in 5.20.1 (fixed bug)
by tye (Sage) on Apr 24, 2015 at 19:26 UTC

    I long considered it a bug that a lack of DESTROY triggered AUTOLOAD. It certainly caused its share of problems. So, somebody finally fixed that bug. Yay.

    - tye        

      That might be the case, but I could not find any documentation about that change and my understanding of the 5.20.1 is that it still is expected to be the old behavior.

        I'm a bit flabbergasted that this was not more loudly advertised. I think i like the change ... it seems awful silly to have to declare a sub that does nothing if you want default behavior. I tried searching for "destroy" from this delta page, but didn't find anything that seemed directly related:

        • Changes to UNIVERSAL::DESTROY now update DESTROY caches in all classes, instead of causing classes that have already had objects destroyed to continue using the old sub. This was a regression in Perl 5.18. (perl #114864)
        • When die, last, next, redo, goto and exit unwind the scope, it is possible for DESTROY recursively to call a subroutine or format that is currently being exited. It that case, sometimes the lexical variables inside the sub would start out having values from the outer call, instead of being undefined as they should. This has been fixed. (perl #119311)
        • Undefining a glob that triggers a DESTROY method that undefines the same glob is now safe. It used to produce "Attempt to free unreferenced glob pointer" warnings and leak memory.
        • If subroutine redefinition (eval 'sub foo{}' or newXS for XS code) triggers a DESTROY method on the sub that is being redefined, and that method assigns a subroutine to the same slot (*foo = sub {} ), $_[0] is no longer left pointing to a freed scalar. Now DESTROY is delayed until the new subroutine has been installed.

        I don't think any of these are directly responsible for the change, but perhaps they might be implicitly? Sorry i don't have an answer, but maybe this will help you track down when it happened. It should be advertised, methinks ... maybe it was in error?


        (the triplet paradiddle with high-hat)
Re: DESTROY and AUTOLOAD in 5.20.1
by Anonymous Monk on Apr 24, 2015 at 18:05 UTC

    "Fascinating," as Mr. Spock would say.

    I do not understand it either, but I can say from experimentation that DESTROY() stopped getting dispatched through AUTOLOAD() starting with Perl 5.18.0. Perl 5.16.3 shows the behavior we both expect. I no longer have 5.17.* available for testing.

    Now, perl5180delta does not contain the word "DESTROY". But perl5200delta notes a bug fix to a change in DESTROY() dispatching that was introduced in 5.18. I wonder if this behavior was introduced at the same time. I also wonder whether this is a bug or a feature. My vote is for the former, based on the principal of least surprise.

    A separate surprising thing (at least to me) is that your code declares DESTROY as though it were a scheduled block, not a subroutine. Well, that in itself does not surprise me, the surprising thing to me is that it works when declared this way. The perlsub documentation refers me to perloo for DESTROY(), and perloo declares it as a subroutine. But the "scheduled block" syntax (i.e. no "sub" keyword) works for every Perl I tried, all the way back to 5.6.2.

    -- Tom Wyant