in reply to Why does this dump core?

I was wondering if deleting keys while iterating over a hash was reallocating the buckets and perhaps Perl was then trying to access memory that's not there. According to Adding or removing keys while iterating over a hash, this is not the case. I can't add, but I should have no problem deleting. Both merlyn and Dominus state that. However, what's vexing about this is that it appears similar to a Perl4 issue where deleting from a hash while iterating over it was verboten. This was fixed in Perl5.

Forgetting the keys should certainly cause the code to fail, but generating a core dump? That's certainly going to cause some people to panic :)

Cheers,
Ovid

Join the Perlmonks Setiathome Group or just click on the the link and check out our stats.

Replies are listed 'Best First'.
Re: (Ovid) Re: Why does this dump core?
by danger (Priest) on Dec 12, 2001 at 01:25 UTC

    That's not the same problem. Your new problem is that you aren't using an iterator (keys(), values(), each()), but just directly evaluating the hash in list context --- and in 5.6.1 that results in the values part of the returned list being the actual values in the hash (instead of copies, as per my previous post). This shouldn't be a real problem because the normal way to do what you are trying to do would be to use keys() in the foreach loop to just iterate over the keys (and thus never be in the position of having an alias to a hash-value that no longer exists). There is no 'forgetting' of keys going on in your problem, your code is deleting a *value* that the foreach-list already has an alias to (because you used foreach (%hash) instead of foreach (keys %hash)).

    Granted, this shouldn't segfault --- it doesn't when warnings are turned on (at least on 5.6.1 on linux). However, you can cause the same sort of behaviour on an array if you foreach over a list of array elements and remove (splice()) an element from the array before we get there in the list (segfaults on 5.00503 and 5.6.1, linux):

    my @array = (0,1,2); foreach my $el ($array[0],$array[1],$array[2]){ print ">>$el<<\n"; splice(@array,1,1) if $el == 0; }