Perl中共享哈希与本地化哈希元素是否存在bug?
共享哈希本地化元素后残留undef项的问题
我写了一段Perl代码,看起来像是个bug,但不确定是不是自己漏了什么细节。核心问题是:在共享哈希里本地化一个哈希元素后,离开作用域该元素依然存在(值为undef)。
示例代码
use threads; use threads::shared; my $hash1 = {}; { local $hash1->{'desc'} = "blah" } print exists($hash1->{'desc'}) ? "Hash: exists\n" : "Hash: does not exist\n"; my $hash2 = shared_clone({}); { local $hash2->{'desc'} = "blah" } print exists($hash2->{'desc'}) ? "Shared hash: exists\n" : "Shared hash: does not exist\n"; print "Shared hash: is undef\n" if !defined($hash2->{'desc'});
运行输出(Perl v5.34.0)
Hash: does not exist Shared hash: exists Shared hash: is undef
对比已修复的类似问题
我查到Perl v5.8.0中修复过一个绑定哈希的类似bug,但不确定共享哈希和绑定哈希是否不同,导致这个问题还存在。
perldoc perl58delta中记录的修复内容:
如果本地化前哈希元素(以及%ENV)不存在,本地化后会正确恢复为不存在的状态。
use Tie::Hash; tie my %tied_hash => 'Tie::StdHash'; ... # 目前尚未设置FOO元素 { local $tied_hash{FOO} = 'Bar' } # 以前会打印该内容,现在不会了。 print "exists!\n" if exists $tied_hash{FOO};此修复的副作用是,绑定哈希接口必须定义EXISTS和DELETE方法。
问题原因分析
共享哈希的底层实现和普通绑定哈希存在差异,threads::shared模块的共享哈希没有完全适配Perl核心对本地化元素的处理逻辑。普通哈希在本地化不存在的元素时,离开作用域会彻底删除该元素;但共享哈希在本地化操作后,仅将元素值设为undef,并未移除键本身,这属于threads::shared模块的遗留问题,而非Perl核心bug。
内容的提问来源于stack exchange,提问作者Michael Krebs
相关产品推荐
相关产品推荐

