Beefy Boxes and Bandwidth Generously Provided by pair Networks
go ahead... be a heretic
 
PerlMonks  

Perl segfault and global destruction problem

by Hofmator (Curate)
on Jan 09, 2004 at 10:49 UTC ( [id://320069]=perlquestion: print w/replies, xml ) Need Help??

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

This is a follow-up on djantzen's post Depth First Search through Digraph Results in Memory Leak.

I played around and simplified the program as far as possible, ending up at the following:

use strict; use warnings; sub UNIVERSAL::DESTROY { warn "DESTROYING @_\n"; } sub dfs { my ($node, $sub) = @_; my %visited; my $dfs; $dfs = sub { my ($n) = @_; $visited{$n}++; $sub->($n); for (@$n) { next unless ref; $dfs->($_->[0]) unless $visited{$_->[0]}; } }; $dfs->($node); } sub do_dfs { my ($node) = @_; my $nodes = []; my $search = sub { push @$nodes, $_[0] }; dfs($node,$search); # UNCOMMENT NEXT LINE to see bug # return $nodes; my @nodes = @$nodes; undef $nodes; return [@nodes]; } warn "STARTING\n"; { my $node1 = bless [1], "Node"; my $node2 = bless [2], "Node"; push @$node1, bless [$node2], "Link"; { my $nodes = do_dfs($node1); warn "Neighbors\n"; warn " $_\n" for (@$nodes); } } warn "SHOULD BE THE LAST THING PRINTED.\n";

This gives the following expected output:

STARTING Neighbors Node=ARRAY(0x8148a8c) Node=ARRAY(0x8148b94) DESTROYING Node=ARRAY(0x8148a8c) at segfault.pl line 6. DESTROYING Link=ARRAY(0x818fc00) at segfault.pl line 6. DESTROYING Node=ARRAY(0x8148b94) at segfault.pl line 6. SHOULD BE THE LAST THING PRINTED.

However, uncommenting the indicated line, leads to the follwing output and a segfault.

STARTING Neighbors Node=ARRAY(0x8148a8c) Node=ARRAY(0x8148b94) SHOULD BE THE LAST THING PRINTED. DESTROYING Node=ARRAY(0x8148a8c) at segfault.pl line 6 during global d +estruction. DESTROYING Link=ARRAY(0x818fc48) at segfault.pl line 6 during global d +estruction. DESTROYING Node=ARRAY(0x8148b94) at segfault.pl line 6 during global d +estruction. DESTROYING IO::Handle=IO(0x818fc6c) at segfault.pl line 6 during globa +l destruction. DESTROYING IO::Handle=IO(0x815c018) at segfault.pl line 6 during globa +l destruction.
  • Why is the order of destruction changed?
  • Where do the two IO::Handles come from?
  • Why the segfault?

I'm on Linux running perl 5.8.0. Can someone confirm with other versions of perl?

Update
OK, summing up the results other people got, the follwoing perls segfault

  • 5.6.1
  • 5.8.0
and these perls do not segfault:
  • 5.005_03
  • 5.6.0
  • 5.6.1d
  • 5.6.2
  • 5.8.1
  • 5.8.2
  • 5.8.3-RC1

What is still consistenly wrong is destruction order. The objects referenced in $node1 and $node2 should be destroyed on block exit not during global destruction, shouldn't they?

-- Hofmator

Replies are listed 'Best First'.
Re: Perl segfault and global destruction problem
by borisz (Canon) on Jan 09, 2004 at 11:11 UTC
    With perl 5.8.1 no segfaults.
    STARTING Neighbors Node=ARRAY(0x8151be0) Node=ARRAY(0x8151cf4) DESTROYING Node=ARRAY(0x8151be0) DESTROYING Link=ARRAY(0x819ced4) DESTROYING Node=ARRAY(0x8151cf4) SHOULD BE THE LAST THING PRINTED. STARTING Neighbors Node=ARRAY(0x8151be0) Node=ARRAY(0x8151cf4) SHOULD BE THE LAST THING PRINTED. DESTROYING Link=ARRAY(0x819cee4) DESTROYING Node=ARRAY(0x8151cf4) DESTROYING Node=ARRAY(0x8151be0) DESTROYING IO::Handle=IO(0x819cf50) DESTROYING IO::Handle=IO(0x8167af0) DESTROYING IO::Handle=IO(0x8167b5c) DESTROYING IO::Handle=IO(0x8165a6c)
    Boris
Re: Perl segfault and global destruction problem
by PodMaster (Abbot) on Jan 09, 2004 at 11:14 UTC
    Except when I note there is no segfault, there is a segfault. All these are activeperl flavored perls (d stands for debug version).
    E:\>perl C:\dev\loose\perl.segfault.320069.pl STARTING Neighbors Node=ARRAY(0x1abf0f8) Node=ARRAY(0x1abf1b8) SHOULD BE THE LAST THING PRINTED. DESTROYING Node=ARRAY(0x1abf0f8) DESTROYING Link=ARRAY(0x1ab51bc) DESTROYING Node=ARRAY(0x1abf1b8) E:\>G:\perl\bin\perl C:\dev\loose\perl.segfault.320069.pl STARTING Neighbors Node=ARRAY(0x15d5014) Node=ARRAY(0x15d50d4) SHOULD BE THE LAST THING PRINTED. DESTROYING Node=ARRAY(0x15d50d4) DESTROYING Link=ARRAY(0x15d4f30) DESTROYING Node=ARRAY(0x15d5014) DESTROYING IO::Handle=IO(0x1a41d80) E:\>G:\perls\5.6.0\bin\perl C:\dev\loose\perl.segfault.320069.pl STARTING Neighbors Node=ARRAY(0x85d24f0) Node=ARRAY(0x85d258c) SHOULD BE THE LAST THING PRINTED. DESTROYING Node=ARRAY(0x85d24f0) DESTROYING Link=ARRAY(0x85df600) DESTROYING Node=ARRAY(0x85d258c) DESTROYING IO::Handle=IO(0x85df564) DESTROYING IO::Handle=IO(0x85dca54) DESTROYING IO::Handle=IO(0x85dcb14) E:\>echo NO SEGFAULT on 5.6.0 NO SEGFAULT on 5.6.0 E:\>G:\perls\5.6.1\bin\perl C:\dev\loose\perl.segfault.320069.pl STARTING Neighbors Node=ARRAY(0x1abf0f8) Node=ARRAY(0x1abf1b8) SHOULD BE THE LAST THING PRINTED. DESTROYING Node=ARRAY(0x1abf0f8) DESTROYING Link=ARRAY(0x1ab5100) DESTROYING Node=ARRAY(0x1abf1b8) E:\>G:\perls\5.6.2\bin\perl C:\dev\loose\perl.segfault.320069.pl STARTING Neighbors Node=ARRAY(0x1a7f0f8) Node=ARRAY(0x1a7f1b8) SHOULD BE THE LAST THING PRINTED. DESTROYING Node=ARRAY(0x1a7f0f8) DESTROYING Link=ARRAY(0x1a75364) DESTROYING Node=ARRAY(0x1a7f1b8) DESTROYING IO::Handle=IO(0x1a752c8) DESTROYING IO::Handle=IO(0x1a77d34) DESTROYING IO::Handle=IO(0x1a7522c) E:\>echo NO SEGFAULT ON 5.6.2 either NO SEGFAULT ON 5.6.2 either E:\>G:\perls\5.8.1\bin\perl C:\dev\loose\perl.segfault.320069.pl STARTING Neighbors Node=ARRAY(0x15d5050) Node=ARRAY(0x15d5110) SHOULD BE THE LAST THING PRINTED. DESTROYING Link=ARRAY(0x1a6f05c) DESTROYING Node=ARRAY(0x15d5050) DESTROYING Node=ARRAY(0x15d5110) DESTROYING IO::Handle=IO(0x1a41eb4) DESTROYING IO::Handle=IO(0x1a41f74) DESTROYING IO::Handle=IO(0x1a41fe0) E:\>echo no segfault no segfault E:\>G:\perls\5.8.2\bin\perl C:\dev\loose\perl.segfault.320069.pl STARTING Neighbors Node=ARRAY(0x15d5060) Node=ARRAY(0x15d5120) SHOULD BE THE LAST THING PRINTED. DESTROYING Link=ARRAY(0x1a6c0bc) DESTROYING Node=ARRAY(0x15d5060) DESTROYING Node=ARRAY(0x15d5120) DESTROYING IO::Handle=IO(0x1a44ff4) DESTROYING IO::Handle=IO(0x1a41f1c) DESTROYING IO::Handle=IO(0x1a41fdc) E:\>echo no_segfault no_segfault E:\> E:\>G:\perls\5.005_03\bin\perl C:\dev\loose\perl.segfault.320069.pl STARTING Neighbors Node=ARRAY(0x365820) Node=ARRAY(0x365844) SHOULD BE THE LAST THING PRINTED. DESTROYING Node=ARRAY(0x365820) DESTROYING Link=ARRAY(0x36f760) DESTROYING Node=ARRAY(0x365844) DESTROYING IO::Handle=IO(0x36f6dc) DESTROYING IO::Handle=IO(0x36c8ec) DESTROYING IO::Handle=IO(0x36c9ac) E:\>echo nosegfault nosegfault E:\>G:\perls\5.6.1d\bin\perl C:\dev\loose\perl.segfault.320069.pl STARTING Neighbors Node=ARRAY(0x1a7f118) Node=ARRAY(0x1a7f1d8) SHOULD BE THE LAST THING PRINTED. DESTROYING Node=ARRAY(0x1a7f118) DESTROYING Link=ARRAY(0x1a75384) DESTROYING Node=ARRAY(0x1a7f1d8) DESTROYING IO::Handle=IO(0x1a752e8) DESTROYING IO::Handle=IO(0x1a77d54) DESTROYING IO::Handle=IO(0x1a7524c) E:\>echo nosegfault nosegfault

    MJD says "you can't just make shit up and expect the computer to know what you mean, retardo!"
    I run a Win32 PPM repository for perl 5.6.x and 5.8.x -- I take requests (README).
    ** The third rule of perl club is a statement of fact: pod is sexy.

Re: Perl segfault and global destruction problem
by liz (Monsignor) on Jan 09, 2004 at 11:12 UTC
    Why the segfault?

    I can't answer that. What I can see is that this does not segfault in 5.8.1, 5.8.2 and 5.8.3-RC1. So I guess this was fixed in 5.8.1.

    Hope this helps.

    Liz

Re: Perl segfault and global destruction problem
by maa (Pilgrim) on Jan 09, 2004 at 11:16 UTC

    Confirmed:

    ActiveState Perl 5.6.1 on Win NT4 SP6a...

    STARTING
    Neighbors
      Node=ARRAY(0x1b9ee88)
      Node=ARRAY(0x1b9ef48)
    SHOULD BE THE LAST THING PRINTED.
    DESTROYING Node=ARRAY(0x1b9ee88)
    DESTROYING Link=ARRAY(0x1b952cc)
    DESTROYING Node=ARRAY(0x1b9ef48)
    
    Crashed with...
    The instruction at "0x28071ad3" referenced memory at <blah> whcih could not be read.
    which is what happens when you write a program that uses a pointer wrongly in C...

hash order
by Anonymous Monk on Jan 09, 2004 at 15:49 UTC
    If I'm not mistaken, those objects are stored internally by a hash table, so any tweaks to this would change the order in which they are destroyed. If you don't explicitly blow them away (and you don't) then you're subject to the joys of whatever order they are in when they come out of the hash.

    Your problem is that your subnodes are destroyed before the parent node, but the parent still has a link to them. When the parent goes away, the ref count for the subnodes drops to 0 and then they get destroyed. But since they've already been destroyed, there is a problem.

    Putting these two together the solution is to walk your tree, and delete the links between the nodes. That breaks the interdependancies and should get you on your way.

    Or haven't had enough caffeine yet, in which case you're on your own.

    - doug

    PS: I have no idea what those IO::Handles are doing there.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://320069]
Approved by broquaint
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others examining the Monastery: (4)
As of 2024-04-20 02:36 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found