Beefy Boxes and Bandwidth Generously Provided by pair Networks
Just another Perl shrine

Oh my God! Tie killed Perl!

by Petruchio (Vicar)
on Jan 14, 2002 at 22:09 UTC ( #138636=perlmeditation: print w/ replies, xml ) Need Help??

(scroll to the bottom for the code)

Cafeteria. Enter Chef, boys.

Chef: Hello there, children!

The boys: Hey, Chef.

Chef: How's it goin'?

The boys: Bad.

Chef: Why bad?

Petruchio: My Perl script won't run right.

Chef: Oh, that's too bad. What's wrong with it?

Perl: Mrgmrmph.

Petruchio: I think it's that stupid tie.

Chef: Woah, hold on there, Petruchio! tye's a very good coder, I'm sure he wouldn't...

Petruchio: Dude, not that tye! You know, the tie that lets you disguise your own object as an ordinary Perl variable, so you can use the nice syntax.

Perl: Mremrmrm

Chef: Oh, I see. Well, you know, children, when I'm fixing one of my recipes, I like to reduce it to a minimal test case. I replace as many variables as possible with literals, remove subroutines so the test is short and linear, and so on. I keep taking things away, but I keep the bug there. Then I can usually see what I've done wrong.

Perl: Mwramergmph.

Petruchio: Oh, you mean like:

perl -e 'package X;sub TIEHASH{bless{},shift};tie my %x,"X";sub DESTROY{untie %x}'

Segementation Fault

Arguile: What the...?

Petruchio: Oh my God! Tie killed Perl!

OeufMayo: Bastard!

Chef: My, my. That's not your bug, Petruchio. Perl shouldn't do that, even though your example is pretty strange. But what are you running? I'm using Perl 5.6.0 on DEC/Alpha, and it's not segfaulting for me.

Petruchio: I'm running 5.6.1 on Debian Linux. Hey! it's not segfaulting if I use Perl 5.005_03 on Debian or FreeBSD. But when I SSH to a Redhat box and run it with 5.6.0, it segfaults and dumps core.

OeufMayo: Dude, Win32 5.6.1 segfaults too!

Arguile: Shall I try on 5.6.1 for FreeBSD, and the shame version for OSX? Schweet! A shegfault on FreeBSD, and a bus error on MacOSX. But I'm on that over an SSH connection so it might be shegfault as well.

Chef: But Petruchio, what were you trying to do, anyway? You know the DESTROY sub only gets called after the UNTIE sub, so why are you calling untie there?

Petruchio: Oh, I know, Chef. I was getting strange errors and unexpected exits because I was storing a reference to the variable being tied in a lexical array. You know, a flyweight object. The variable's original value seems to disappear when you tie it, and reappear again when you untie it. It's a lot like local. In fact, I suspect it uses the same mechanism somehow.

Chef: I see. But...

Petruchio: Anyway, I wanted the tied variable to keep the values it had just before it was untied. So I kept a reference to it in the lexical array, and then tried to reset the value during the DESTROY block, once the underlying variable had been uncovered.

Chef: I see. But don't you think...

Petruchio: And really weird stuff happens when you you start tying the different elements in a tied hash or array... and then if you alias typeglobs to them...

Arguile: Dude, your schript sucks.

Petruchio: Shut up, Arguile!

Chef: Well... Petruchio... didn't Mr. Tilly tell you not to go abusing tie like that?

Petruchio: Yeah, I know. They're all really objects anyway, and by pushing tie too far I'm making the code more complex and error-prone. Tie should make things easier. But it was interesting, and now I understand tie better.

Chef: Oh, I understand. I like a little syntactic sugar myself, heh, heh. Expressing love so sweet... baby, you know I want to... taste that sugar...

Petruchio: Chef?

Chef: Oh, uh... yeah, Petruchio?

Petruchio: Here's the important part of my code:

#!/usr/bin/perl package Eraseme; use strict; use Data::Dumper; my @object; tie my %x, 'Eraseme'; print "Outside:\n"; print Dumper( \@object ); #print keys %{ $object[0][0] }; print "Uncommenting this won't prevent + it.\n"; #print Dumper( $object[0][0] ); print "Uncommenting this won't either. +\n"; #untie %x; print "Uncommenting this, however, prevents the error.\n"; sub TIEHASH { push @object, [ \%x ]; my $ret = bless { }, 'Eraseme'; print "Inside:\n"; print Dumper( \@object ); $ret; } sub DESTROY { # print Dumper( $object[0][0] ); print "Uncomment this. See? It exite +d.\n"; # untie %x; print "Uncomment this, and Segfault! +.\n"; print keys %{ $object[0][0] }; print "Destroyed\n"; } sub FIRSTKEY { } sub STORE { } sub FETCH { } sub NEXTKEY { } sub EXISTS { } sub DELETE { } sub CLEAR { }

Chef: Well, isn't that something? Says, (in cleanup) Can't call method "FIRSTKEY" on an undefined value at ./ line 31 during global destruction.

Petruchio: Yeah! Only the one-liner didn't segfault for you, so it can't be the same bug, can it?

Chef: I don't know, Petruchio. It could still be your bug. you know. Why don't you ask your little PerlMonk friends to look at it? Some of them might have some interesting things to say about it.

Petruchio: Yeah! I'll write it up! Thanks, Chef.

Arguile: Come on. I want some Cheesy Poofs.

Exeunt boys

Chef: My, my, they do get themselves into trouble. Oh my gosh! It's almost noon - I'll be late for the award ceremony! hmm hmm hmm... You know... Kathy Lee... you are a very special woman...

Exit Chef

Update - many thanks to tye for educating me on the proper use of the word 'exeunt'. It means, 'they go out', and is used particularly when speaking in the plural. The boys exeunt, the Chef exits.

Comment on Oh my God! Tie killed Perl!
Select or Download Code
Re: Oh my God! Tie killed Perl!
by Rich36 (Chaplain) on Jan 14, 2002 at 22:19 UTC
    Informative and entertaining. Kick ass!
    "Ties are bad, m'kay."
    There's more than one way to screw it up...

by tye (Cardinal) on Jan 14, 2002 at 22:36 UTC

    Just a quick note that globals get destroyed in somewhat random order and that can often result in references turning into undef in the middle of "global destruction". Actually, they are still references (because ref returns a true value), they just have an address of 0 (they return 0 in a numeric context), which Perl reports as "undef" when you actually try to use it.


    That only partially addresses one of your questions, but that was all I have time for at the moment. (:

    Update: Hmm, you aren't using any globals so this probably isn't the problem, though. Hmm...

    Oh, wait. You have hard-coded references to your lexical %x in your subroutines. This means that %x won't be freed until those subroutines are freed and subroutines don't get freed until "the end". Change your code so that \%x is passed in to TIEHASH (and keep the reference to it commented out in DESTROY) and see how that changes things.

            - tye (but my friends call me "Tye")



      The fix was also discussed in the p5p digest.






                - tye (but my friends call me "Tye")
Re: Oh my God! Tie killed Perl!
by perrin (Chancellor) on Jan 15, 2002 at 01:01 UTC

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: perlmeditation [id://138636]
Approved by root
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others chilling in the Monastery: (12)
As of 2014-12-25 11:00 GMT
Find Nodes?
    Voting Booth?

    Is guessing a good strategy for surviving in the IT business?

    Results (160 votes), past polls