in reply to Re: Use of freed value in iteration
in thread Use of freed value in iteration

After doing a simple test this definitely is the case. If I simply push a string onto an array after deleting the hash key $v ends up getting the string. On my machine the following code prints:
HASH(0xa00003da0) HASH(0xa00003f38) HASH(0xa00003da0) hello
my $hr1 = {}; my $hr2 = {}; my $hr3 = {"$hr1" => $hr1, "$hr2" => $hr2}; my @values = sort values %$hr3; print "@values\n"; my (@arr); foreach my $v (sort values %$hr3) { print "$v\n"; delete $hr3->{$values[1]}; push @arr, "hello"; }
This seems very dangerous.

Replies are listed 'Best First'.
Re^3: Use of freed value in iteration
by swl (Prior) on Feb 12, 2024 at 21:26 UTC

    The code is modifying the hash while iterating over its values and using those values as the keys for deletion. You perhaps already tried this, but if you change the loop to iterate over @values or the keys of $hr3 then the issue disappears. Same if you stringify the loop iterator $v.

    Others can better comment on the details, but I assume perl is re-using memory and your code is reaching into the old locations.

      Yes, that is the point. The warning "Use of freed value in iteration" is great for catching bugs, but it can easily fail to catch one if the memory location of the deleted item is replaced with something else. If that something else happens to be the same type as the original item, then it could be a really insidious bug.
      "but if you change the loop to iterate over @values or the keys of $hr3 then the issue disappears"

      Yeah, iterating over @values would be really bad if you wanted to ensure you are only dealing with things defined in $hr3. Iterating over the keys of %$hr3 is definitely the safer way to go. That way when $hr3->{$key} is accessed you'll get a warning if it doesn't exist.

        I wonder if this is an example of the stack not being ref-counted. Hopefully someone is able to test with a recent 5.39 perl with the ref-counted stack enabled.

        (Edited grammar after posting).

Re^3: Use of freed value in iteration
by Danny (Chaplain) on Feb 13, 2024 at 17:30 UTC
    For completeness, this value replacement also occurs when iterating over values of an array, and the replacement value can be from a new hash key or a new array element. The following code
    my @arr = ("item 1","item 2"); my %h; foreach my $v (values @arr) { print "$v\n"; delete $arr[1]; $h{x} = "sneaky hash value" } @arr = ("item 1","item 2"); my @arr2; foreach my $v (values @arr) { print "$v\n"; delete $arr[1]; push @arr2, "sneaky array value"; }
    produces
    item 1 sneaky hash value item 1 sneaky array value