What am I missing here?
When passing arguments to Net::Ping like this, then $args and $args_copy will both be set to an empty hashref after initializing the constructor Net::Ping->new($args).
use strict;
use warnings;
use Data::Dumper qw(Dumper);
use Net::Ping;
sub _ping {
my ($args) = @_;
my $p = Net::Ping->new($args);
$p->close();
}
my $args = { proto => 'udp' };
my $args_copy = $args;
print Dumper $args; # $VAR1 = { 'proto' => 'udp' }
print Dumper $args_copy; # $VAR1 = { 'proto' => 'udp' }
_ping($args);
print Dumper $args; # $VAR1 = {}
print Dumper $args_copy; # $VAR1 = {}
I see the same behavior on both Strawberry Perl and WSL2 running Ubuntu 20.04.4 LTS with Perl v5.30.0.
This is interesting, a class (constructor) deleting caller's data.
The shown code passes a reference to the
Net::Pingconstructor and that data gets cleared, and right in the constructor (see below).To avoid having
$argscleared, if that is a problem, pass its copy insteadThis first de-references the hash and then constructs an anonymous hash reference with it,† and passes that. So
$argsis safe.The constructor new uses data from
@_directly (without making local copies), and as it then goes through the keys it also deletes them, I presume for convenience in further processing. (I find that scary, I admit.)Since a reference is passed to
newthe data in the calling code can get changed.‡† When copying a hash (or array) with a complex data structure in it -- when its values themselves contain references -- we need to make a deep copy. One way is to use Storable for it
Here that would mean
_ping( dclone $args );. It seems thatnewcan only take a reference to a flat hash (or scalars) so this wouldn't be necessary.‡ When a sub works directly with the references it gets then it can change data in the caller
However, if a local copy of arguments is made in the sub then caller's data cannot be changed
(Just remember to not touch
$ref_databut to use the local copy.)This way of changing data in the caller is of course useful when the sub is meant to work on data structures with large amounts of data, since this way they don't have to be copied. But when that is not the purpose of the sub then we need to be careful, or just make a local copy to be safe.