gpt4 book ai didi

perl - 受限哈希更新不是原子的,只有 `lock_keys` 而不是 `lock_hash`

转载 作者:行者123 更新时间:2023-12-04 03:36:13 24 4
gpt4 key购买 nike

在 OS X 上使用 Perl 5.24 测试

我试图弄清楚为什么仅当哈希的 受到限制时,尝试更新受限哈希才会清除哈希表(违反原子性)。如果lock_hash已经应用到hash,那么非法修改被完全回滚。

Hash::Util 声明的部分文档。

CAVEATS

Note that the trapping of the restricted operations is not atomic: for example

eval { %hash = (illegal_key => 1) }

leaves the %hash empty rather than with its original contents.

我最初想看看像更新单个非法 key 这样的个别操作是否是原子的,以及 Perl 5.24 是否会在这种情况下发出警告,但是当我第一次尝试时我无法重现该行为。

#!/usr/bin/env perl
use strict;
use warnings FATAL => 'all';
use Hash::Util qw[lock_hash lock_keys];
use Data::Dumper;

my %hash = (a => 1, b => 2);
lock_hash(%hash);

eval { %hash = (illegal_key => 1) };

print Dumper \%hash;

这打印

$VAR1 = {
'a' => 1,
'b' => 2
};

但是,使用 lock_keys 确实会重现该行为

#!/usr/bin/env perl
use strict;
use warnings FATAL => 'all';
use Hash::Util qw[lock_hash lock_keys];
use Data::Dumper;

my %hash = (a => 1, b => 2);
lock_keys(%hash);

eval { %hash = (illegal_key => 1) };

print Dumper \%hash;

打印一个空的 hashref,正如文档所预言的那样

$VAR1 = {};

为什么根据散列的限制方式,行为会有所不同?

最佳答案

我尝试了两个不同版本的 Perl 5.10.1 和 5.18.2,行为与您的相同,使用旧版本的 Perl 时可能存在一些限制。

lock_hash 和 lock_key 略有不同。

当您调用 lock_hash 时,它会:

lock_keys(%$hash);

foreach my $key (keys %$hash) {
lock_value(%$hash, $key);
}

因此它在 lock_keys 时锁定了哈希的键和值:

Internals::hv_clear_placeholders %$hash;
if( @keys ) {
my %keys = map { ($_ => 1) } @keys;
my %original_keys = map { ($_ => 1) } keys %$hash;
foreach my $k (keys %original_keys) {
die sprintf "Hash has key '$k' which is not in the new key ".
"set at %s line %d\n", (caller)[1,2]
unless $keys{$k};
}

foreach my $k (@keys) {
$hash->{$k} = undef unless exists $hash->{$k};
}
Internals::SvREADONLY %$hash, 1;

foreach my $k (@keys) {
delete $hash->{$k} unless $original_keys{$k};
}
}
else {
Internals::SvREADONLY %$hash, 1;
}

我假设这是一个错误,因为您锁定了键而不是哈希,然后当您尝试修改时它返回一个空哈希。

但是有些人已经在这个问题上经历过与您类似的事情:

Should I use Internals::SvREADONLY for creating readonly variables in Perl?

还有其他方法可以执行您想要的操作,例如使用 TIE 或 Readonly。

如果您想看一下,这里还有一份关于内部结构的文档:

Internals Documentation

不幸的是,不鼓励这种做法:

SvREADONLY(THING, [, $value])

Set or get whether a variable is readonly or not. Exactly what the readonly flag means depend on the type of the variable affected and the version of perl used.

You are strongly discouraged from using this function directly. It is used by various core modules, like Hash::Util, and the constant pragma to implement higher-level behavior which should be used instead.

See the core implementation for the exact meaning of the readonly flag for each internal variable type.

关于perl - 受限哈希更新不是原子的,只有 `lock_keys` 而不是 `lock_hash`,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41374235/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com