2014-03-28 59 views
3

散列使用each()插入而不復位未定義的行爲哈希迭代後的結果,Perl解釋:0x13932010/srv/data203806/MUXmh-Migration/Newperl/localperl/lib/site_perl/5.18.1/x86_64-linux-thread-multi/forks.pm線1736如何在插入警告後禁止散列?

一切都在我的代碼工作正常,但我發現這個錯誤。我怎樣才能壓制這個警告?

+2

警告告訴你正在做某件你不被允許的事情。這不是一個虛假的警告;你應該解決問題而不是沉默警告。 – ikegami

回答

10

此警告說:

use strict; 
use warnings; 
use Data::Dumper; 

my %h = (a=>1); 
while (my ($k,$v) = each %h) { 
    $h{b} = 2; 
} 

print Dumper \%h; 

這沉默的警告:

use strict; 
use warnings; 
use Data::Dumper; 

my %h = (a=>1); 
{ 
    no warnings qw(internal); 
    while (my ($k,$v) = each %h) { 
     $h{b} = 2; 
    } 
} 

print Dumper \%h; 

注意的警告類別的沉默被稱爲internal。我怎麼知道這件事的?對於Perl的警告類別,我有什麼驚人的記憶嗎?不可以。所有Perl的錯誤和警告消息均已在perldiag中詳細記錄;對於每個警告,它都會提及它所屬的類別。

這就是說,這個警告告訴你一個真正的問題。你的代碼的行爲是未定義的;如果您切換到不同版本的Perl,它可能突然開始採取不同的行爲。比關閉警告更好的是修復你的代碼!

在我上面的例子中,速戰速決將通過副本%h而非%h本身使用each循環。

use strict; 
use warnings; 
use Data::Dumper; 

my %h = (a=>1); 
{ 
    my %tmp = %h; 
    while (my ($k,$v) = each %tmp) { 
     $h{b} = 2; 
    } 
} 

print Dumper \%h; 
-1

下面的技術,其現有的代碼最小的變化,避免危險動作抑制警告:

foreach my $key (keys %hash) { 
    my $value = $hash{$key}; 
    # ... 
} 

$價值的分配,確保您無需返工下面的代碼包含塊。

+0

請不要回答代碼 – danopz

1

這裏真正的問題是:會發生什麼?文件說它是未定義的。作爲一名Perl編碼人員,我可以忍受這一點。我個人並不在乎每個設置()會返回到哪個位置。有幾種可能性,但在我詳細說明之前,我應該說我使用each()是一個可憐的人類迭代器,因爲內置比每個()更好。

所以排隊是: - 從鍵/值集返回一些隨機對,然後按預期形式在那裏繼續。 (這對我來說沒問題,我沒有添加東西) - 重新開始。顯然這沒有發生,或者文件會這樣說。 (我不贊成這個動作) - each()返回(undef,undef)集合,然後按預期工作。不是我的第一選擇,但時好時好,如果它碰巧是未定義的可能性之一。 - 失去理智;我會在這裏使用一個豐富多彩的比喻,但基本上放鬆了所有的控制,而Perl自我打破。盡我所能,這不會發生。

由於其他貢獻者建議最好進行編碼,因此不會創建警告;但是我提供了一個例子(簡單的迭代器),我以較高的頻率(較高)擊中每一個,並以較低的頻率插入和移除項目。我發現Perl的行爲減去完全適合的警告消息。

在一些我需要更好的迭代器控制的情況下,我創建了一個合適的類來實現我認爲合適的行爲。