http://qs321.pair.com?node_id=623248


in reply to Re: Segmentation fault
in thread Segmentation fault

Hello Joost, big thanks for your fast answer. Yes, if I increase the ulimit the script runs very fine without a stack overflow. Do you know also why the segfault is produced first if the script die and not immediate?

Replies are listed 'Best First'.
Re^3: Segmentation fault
by Joost (Canon) on Jun 25, 2007 at 20:47 UTC
    Do you know also why the segfault is produced first if the script die and not immediate?
    The stack-overflow is triggered when the top-level hash goes out of scope. In your example that is when the script ends, but that's just coincidental. If your hash goes out of scope before that, and your stack-size isn't big enough, you'll get a segfault at that point:

    { my $i = 60000; my %h = (new => {}); my $r = \%h; for (0..$i) { print $_, " "; $r = $r->{new}; $r->{new} = {}; } print "end 1\n"; } # <-- hash goes out of scope; segfault if stacksize is too low print "end 2\n";
    I'm not familiar with the implementation of perl's garbage collector, but I've seen this problem once before. In that case as in this one, the problem was caused by a program letting a long linked list (i.e. item a has a reference to item b which has a reference to item c etc. etc.) go out of scope.

    If you're really careful, you can clean up the linked list before it goes out of scope and prevent this error:

    { my $i = 60000; my %h = (new => {}); my $r = \%h; my $end = $r; # end of the list for (0..$i) { print $_, " "; $r = $r->{new}; $r->{new} = {}; $r->{new}->{old} = $r; # keep back-references $end = $r->{new}; } print "end 1\n"; while ($end) { # delete the list from the end delete $end->{new}; $end = delete $end->{old}; } } print "end 2\n";
      If you're really careful, you can clean up the linked list before it goes out of scope and prevent this error:

      [two-way linked list example]

      True, but way too much trouble. You may keep the original structure and just add a non-recursive disassembly:

      my $i = 30000; my %h = (new => {}); my $r = \%h; for (0..$i) { print $_, "\r"; $r = $r->{new}; $r->{new} = {}; } $r = $h{new}; undef %h; while ($r) { $r = $r->{new}; } print "end\n";