1) It definitely is a stack-not-refcounted problem. The warning tells you that you are subject to undefined behaviour: that could mean a crash or having your hard disk formatted, as well as just getting the wrong answer. The warning is telling you that the code needs changing, at least for any perl that isn't refcounting stack items.
2) If you change your code to iterate over the keys, then you can check whether the value exists by the time you come to process it, and take whatever avoiding action is appropriate:
my $hr1 = {};
my $hr2 = {};
my $hr3 = {"$hr1" => $hr1, "$hr2" => $hr2};
my @values = sort values %$hr3;
print "@values\n";
my (@arr);
foreach my $k (sort { $hr3->{$a} cmp $hr3->{$b} } keys %$hr3) {
unless (exists $hr3->{$k}) {
warn "key '$k' deleted during loop\n";
next;
}
my $v = $hr3->{$k};
print "$v\n";
delete $hr3->{$values[1]};
push @arr, "hello";
}
HASH(0x560669c681e0) HASH(0x560669c683c0)
HASH(0x560669c681e0)
key 'HASH(0x560669c683c0)' deleted during loop
| [reply] [d/l] |
That seems like a good feature instead of a problem.
dave_the_m has done (and continues to do) quite a bit of work on refcounting the stack.
You can check on the progress by building blead with the -DPERL_RC_STACK added to ccflags.
IIRC, on linux builds, just add -Accflags=-DPERL_RC_STACK to the Configure args.
Here's a simple demo of the issue, posted a while back by Dave (on the p5p mailing list, I think):
@a = qw(aaa bbb);
f(@a);
sub f {
# on entry, $_[0] is an alias of $a[0],
# $_[1] is an alias of $a[1],
print "@_\n"; # correctly prints "aaa bbb"
@a = (); # this prematurely frees $_[0] and $_[1]
# this causes the two just-freed SVs to be reallocated
my $x = 'xxx:yyy'; my @x = split /:/, $x;
# but the two reallocated SVs are still referenced by @_
print "@_\n"; # incorrectly prints "xxx yyy"
}
Four months back, I built the then-current devel release (perl-5.39.3) with that flag added - just curious to see whether it did something it shouldn't be doing on Windows. (It was fine, of course.)
It fixed that particular demo. The script output became:
aaa bbb
aaa bbb
But there are still other aspects of the issue to be addressed, upon which Dave continues to work.
Cheers, Rob | [reply] [d/l] [select] |
If $_[0] is supposed to be an alias of $a[0] and $_[1] an alias of $a[
+1], I'm not sure I'd want that second print "@_\n" to print aaa bbb.
At least in a loop, if an object has been deleted I'd want that to be noticed when trying to access it. It seems like the desirable behavior, regardless of what the refcount is doing, would be for 1) deleted values occurring within the loop to be reflected if those values are accessed, but 2) the memory occupied by those values couldn't be reused by a different object during the loop. This may be desirable for the subroutine behavior also.
| [reply] [d/l] [select] |
I'm not sure I'd want that second print "@_\n" to print aaa bbb.
I'd want it to. Consider this:
my @a = qw(aaa bbb);
my $r = \$a[0];
@a = ();
print $$r;
I'd expect that to print "aaa". This is pretty much at the heart of the reference-counting model at the heart of perl. Similarly to how the fact that the lexical var getting freed on scope exit doesn't free the return value in:
sub f { my $x = ...; return $x }
Dave. | [reply] [d/l] [select] |