我的项目中有这个:
sub get_src_info($) {
my $package = shift;
my ($key,$value,$tail) =("","","");
my (@APT_INFO,$r);
open APT, "apt-cache showsrc $package|";
while (<APT>){
chomp;
($key,$value,$tail) = split /:/;
if (defined ($key) && defined ($value)) {
$value =~ s/^\s+|\s+$//;
if (defined($tail)) {
$value = "$value:$tail";
}
if ( $key eq "Package" or $key eq "Version" ) {
$r->{$key} = $value;
}
}
if(/^$/) { push @APT_INFO,$r++; }
}
close APT;
return @APT_INFO;
}
我通常使用use strict
来检查错误。
代码使用no strict "refs";
指令,但没有它就无法运行,产生错误:
Can't use string ("163277181") as a HASH ref while "strict refs" in use at a.pl line 61, <APT> line 45.
第61行是:$r->{$key} = $value;
我更喜欢修复我的代码,而不是让它沉默,但却无法解决错误/如何解决这个问题。
另外,推进引用指向下一个对象的正确方法是什么?虽然它有效但我不认为$r++
在这里是正确的构造。
非常感谢。
答案 0 :(得分:2)
您将$r
变量用作哈希引用$r->{$key}
和数字$r++
。引用编号为ID,因此可以将它们用作数字。但是,您不能使用非引用标量作为引用(引用不是指针)。为了说清楚:
my $reference = { foo => 1 };
my $numified = 0 + $reference; # is now 163277181
say $numified->{foo}; # does not work under strict "refs"
# ${"163277181"}{foo} is equivalent: This looks for global variable %163277181
您可以通过在新块开始时在$r
中创建新引用来解决问题。您还应该正确调整其他变量的范围:不要使用像APT
这样的全局变量,并在循环中声明<{1}}等变量。
此外,$key
永远不会是$key
(undef
不会返回split
个值),您也不应该使用原型。
我想以下代码可以满足您的需求:
undef
您不能在内存安全语言中使用指针算法。 Perl是一种内存安全的语言。您可以使用的引用类似于C中的指针。它们也是键入的(虽然是动态的),但是会自动引用计数,以便在不需要时释放引用的数据结构。垃圾收集和内存安全的支持者指出较少的错误(例如,双use autodie; # automatic error handling, e.g. for `open`
sub get_src_info {
my ($package) = @_;
my $info = {};
my @apt_info;
open my $fh, "-|", "apt", "showsrc", $package; # circumvent the shell for safety
while (<$fh>) {
chomp;
unless (length) {
push @apt_info, $info;
$info = {}; # put a new reference into $info
next;
}
my ($key, $value) = split /:/, $_, 2; # limit number of fragments to 2
next unless $key eq "Package" or $key eq "Version";
s/^\s+//, s/\s+$// for $value; # this trims at *both* ends
$info->{$key} = $value;
}
return @apt_info;
}
)和提高的生产率,尽管某些算法可能不会被优雅地表达。大多数现代语言默认都是内存安全的。
即使这是C,free
指向一个新地址,我也要问你:你不应该$r++
新记忆吗?内存分配隐含在Perl中。 malloc
为我们提供了一个新的空哈希引用。如果使用词法变量(使用$r = {}
),则也会自动释放。