perl5004delta - perl5.004 的新增内容
本文档描述了 5.003 版本(如《编程 Perl》第二版(骆驼书)中所述)与本版本之间的差异。
Perl5.004 在 Unix、Plan 9、LynxOS、VMS、OS/2、QNX、AmigaOS 和 Windows NT 上开箱即用。Perl 也可在 Windows 95 上运行,但由于缺乏合理的命令解释器,无法在该平台上构建。
最重要的是,修复了许多错误,包括几个安全问题。有关详细信息,请参阅发行版中的 Changes 文件。
%ENV = ()
和 %ENV = @list
现在按预期工作(VMS 除外,它会生成致命错误)。
错误“无法在 @INC 中找到 Foo.pm”现在列出了 @INC 的内容,以便于调试。
有一个新的配置问题询问您是否要与 Perl 5.003 保持二进制兼容性。如果您选择二进制兼容性,则无需重新编译扩展,但如果您将 Perl 嵌入到另一个应用程序中,则可能会出现符号冲突,就像在 5.003 版本中一样。默认情况下,二进制兼容性以符号表污染为代价得以保留。
您现在可以将 Perl 选项放在 $PERL5OPT 环境变量中。除非 Perl 在进行污染检查的情况下运行,否则它会将此变量解释为其内容出现在脚本开头的 "#!perl" 行上,只是连字符是可选的。PERL5OPT 只能用于设置以下开关:-[DIMUdmw]。
-M
和 -m
选项不再允许出现在脚本的 #!
行上。如果脚本需要模块,则应使用 use
编译指示调用它。
-T 选项也禁止出现在脚本的 #!
行上,除非它出现在 Perl 命令行上。由于 #!
的工作方式,这通常意味着 -T 必须是第一个参数。因此
#!/usr/bin/perl -T -w
对于以 scriptname
方式调用的可执行脚本来说,可能会起作用,而
#!/usr/bin/perl -w -T
在相同条件下可能会失败。(非 Unix 系统可能不会遵循此规则。)但 perl scriptname
肯定会失败,因为这样就没有机会在 #!
行上找到它之前在命令行上找到 -T。
如果您从 Perl 5.003 脚本中删除了 -w 选项,因为它使 Perl 太冗长,我们建议您在升级到 Perl 5.004 时尝试将其放回。每个新的 perl 版本都倾向于删除一些不需要的警告,同时添加新的警告,这些警告可能会捕获脚本中的错误。
AUTOLOAD
在 Perl 5.004 之前,AUTOLOAD
函数被视为方法(使用 @ISA
层次结构),即使要自动加载的函数被调用为普通函数(例如 Foo::bar()
),而不是方法(例如 Foo->bar()
或 $obj->bar()
)。
Perl 5.005 将仅对方法的 AUTOLOAD
使用方法查找。但是,存在大量可能使用旧行为的现有代码。因此,作为过渡步骤,Perl 5.004 在非方法使用继承的 AUTOLOAD
时发出可选警告。
简单的规则是:当自动加载非方法时,继承将不起作用。对于旧代码的简单修复是:在任何以前依赖于从名为 BaseClass
的基类继承 AUTOLOAD
来处理非方法的模块中,在启动时执行 *AUTOLOAD = \&BaseClass::AUTOLOAD
。
在 5.003 中,使用 %OVERLOAD 定义重载已弃用。现在使用 overload pragma 定义重载。%OVERLOAD 仍在内部使用,但 Perl 脚本不应使用它。有关更多详细信息,请参阅 overload。
在 Perl 5.004 中,用作子程序参数的非存在数组和哈希元素仅在实际分配给它们(通过 @_
)时才会被创建。
早期版本的 Perl 在处理此类参数方面有所不同。Perl 版本 5.002 和 5.003 始终创建它们。Perl 版本 5.000 和 5.001 仅在它们不是第一个参数(这几乎肯定是一个错误)时才创建它们。早期版本的 Perl 从未创建它们。
例如,给定以下代码
undef @a; undef %a;
sub show { print $_[0] };
sub change { $_[0]++ };
show($a[2]);
change($a{b});
在 Perl 5.004 中执行此代码后,$a{b} 存在,但 $a[2] 不存在。在 Perl 5.002 和 5.003 中,$a{b} 和 $a[2] 都将存在(但 $a[2] 的值将是未定义的)。
$)
更改$)
特殊变量始终(至少在 Perl 5 中)反映当前有效的组,以及 getgroups()
C 函数(如果有)返回的组列表。但是,在此版本之前,没有办法从 Perl 调用 setgroups()
C 函数。
在 Perl 5.004 中,对 $)
的赋值与检查它完全对称:其字符串值中的第一个数字用作有效 gid;如果有任何数字在第一个数字之后,它们将传递给 setgroups()
C 函数(如果有)。
5.004 之前的 Perl 版本错误地解释了任何类型标记后跟 "$" 和数字。例如,"$$0" 被错误地解释为 "${$}0" 而不是 "${$0}"。此错误在 Perl 5.004 中已(大部分)修复。
但是,Perl 5.004 的开发人员无法完全修复此错误,因为至少有两个广泛使用的模块依赖于字符串中 "$$0" 的旧含义。因此,Perl 5.004 仍然以旧的(错误的)方式在字符串内部解释 "$$<digit>";但它会生成此消息作为警告。在 Perl 5.005 中,这种特殊处理将停止。
5.004 之前的 Perl 版本并不总是能正确地本地化与正则表达式相关的特殊变量。Perl 5.004 确实对它们进行了本地化,正如文档一直以来所述。这可能会导致 $1、$2 等不再被设置,而现有程序使用它们。
Perl 5.0 的文档一直指出,当一个已经打开的文件句柄在没有调用 close 的情况下重新打开时,$.
不会被重置。由于一个 bug,Perl 5.000 到 5.003 版本在这种情况下确实重置了 $.
;Perl 5.004 不会。
wantarray
可能返回 undefwantarray
运算符如果一个子程序预期返回一个列表,则返回真值,否则返回假值。在 Perl 5.004 中,wantarray
也可以返回 undef 值,如果一个子程序的返回值根本不会被使用,这允许子程序避免在返回值不会被使用的情况下进行耗时的计算。
eval EXPR
在标量上下文中确定 EXPR 的值Perl(版本 5)过去不一致地确定 EXPR 的值,有时会错误地使用周围的上下文进行确定。现在,EXPR 的值(在被 eval 解析之前)始终在标量上下文中确定。一旦解析,它就会像以前一样执行,通过提供 eval 周围的范围提供的上下文。这种改变使行为与 Perl4 兼容,除了修复由于不一致行为导致的 bug。这个程序
@a = qw(time now is time);
print eval @a;
print '|', scalar eval @a;
过去会打印类似 "timenowis881399109|4" 的内容,但现在(以及在 perl4 中)会打印 "4|4"。
先前版本中的一个错误可能导致在启用 taint 检查时无法检测到某些不安全的条件。(taint 检查用于 setuid 或 setgid 脚本,或者在使用 -T
调用选项显式启用时。)虽然不太可能,但这可能会导致以前正常运行的脚本现在失败,这应该被视为一种幸运,因为它表明一个潜在的严重安全漏洞刚刚被堵住了。
taint 检查的新限制包括
这些运算符可能会启动 C shell (csh),而 csh 无法被安全地使用。此限制将在 Perl 的未来版本中解除,届时将实现无需使用外部程序的 glob 功能。
这些环境变量可能会以破坏安全的方式改变启动的程序(尤其是 shell)的行为。因此,现在它们被视为危险,与 $IFS 和 $PATH 相同。
一些 termcap 库对 $TERM 进行了不安全的处理。但是,将所有 $TERM 值都视为不安全将过于苛刻,因为只有 shell 元字符会导致 $TERM 中出现问题。因此,如果一个被 taint 的 $TERM 只包含字母数字、下划线、连字符和冒号,则它被视为安全;如果它包含其他字符(包括空格),则被视为不安全。
新的 Opcode 模块支持创建、操作和应用操作码掩码。修订后的 Safe 模块具有新的 API,并且使用新的 Opcode 模块实现。请阅读新的 Opcode 和 Safe 文档。
在旧版本的 Perl 中,无法在一个进程中创建多个 Perl 解释器实例,而不会像筛子一样泄漏或崩溃。导致这种行为的错误都已修复。但是,在将 Perl 嵌入 C 程序时,您仍然需要小心。有关如何管理解释器的提示,请参阅更新的 perlembed 手册页。
文件句柄现在在内部存储为 IO::Handle 类型。FileHandle 模块仍然为了向后兼容而受支持,但它现在仅仅是 IO::* 模块(特别是 IO::Handle、IO::Seekable 和 IO::File)的前端。我们建议(但不要求)您在新代码中使用 IO::* 模块。
与此更改相一致,*GLOB{FILEHANDLE}
现在只是 *GLOB{IO}
的向后兼容的同义词。
现在可以使用 AT&T 的 sfio IO 包来构建 Perl,而不是 stdio。有关更多详细信息,请参阅 perlapio,以及有关如何使用它的 INSTALL 文件。
子例程引用现在可以后缀一个箭头和一个(可能是空的)参数列表。此语法表示调用引用的子例程,并使用给定的参数(如果有)。
这种新的语法遵循 $hashref->{FOO}
和 $aryref->[$foo]
的模式:现在可以将 &$subref($foo)
写成 $subref->($foo)
。所有这些箭头项都可以链接;因此,&{$table->{FOO}}($bar)
现在可以写成 $table->{FOO}->($bar)
。
编译时的当前包名,或者如果当前没有包(由于 package;
指令),则为未定义的值。与 __FILE__
和 __LINE__
一样,__PACKAGE__
不会插值到字符串中。
某些平台上的扩展错误消息。(如果您 use English
,也称为 $EXTENDED_OS_ERROR)。
由 use strict
启用的当前语法检查集。有关更多详细信息,请参阅 strict
的文档。实际上不是新的,但新文档化了。因为它旨在供 Perl 核心组件内部使用,所以此变量没有 use English
长名称。
默认情况下,内存不足是不可捕获的。但是,如果为此编译,Perl 可能会在使用此消息 die() 后使用 $^M
的内容作为紧急池。假设您的 Perl 使用 -DPERL_EMERGENCY_SBRK 编译并使用 Perl 的 malloc。然后
$^M = 'a' x (1<<16);
将分配一个 64K 缓冲区以在紧急情况下使用。有关如何启用此选项的信息,请参阅 INSTALL 文件。作为对随意使用此高级功能的威慑,此变量没有 use English
长名称。
现在可以使用了。(例如:delete @ENV{'PATH', 'MANPATH'}
)
现在在更多平台上支持,在模拟时优先使用 fcntl 而不是 lockf,并且在(取消)锁定之前始终刷新。
Perl 现在自己实现了这些函数;它不再使用 C 库函数 sprintf(),除了浮点数,即使这样也只允许已知的标志。因此,现在可以知道哪些转换和标志将起作用,以及它们将做什么。
Perl 的 sprintf() 中的新转换是
%i a synonym for %d
%p a pointer (the address of the Perl value, in hexadecimal)
%n special: *stores* the number of characters output so far
into the next variable in the parameter list
在 %
和转换之间的新标志是
# prefix octal with "0", hex with "0x"
h interpret integer as C type "short" or "unsigned short"
V interpret integer as Perl's standard integer type
此外,在标志中出现数字的地方,可以使用星号("*")代替,在这种情况下,Perl 将使用参数列表中的下一个项目作为给定数字(即,作为字段宽度或精度)。如果通过 "*" 获得的字段宽度为负数,则它与 "-" 标志具有相同的效果:左对齐。
有关转换和标志的完整列表,请参见 "perlfunc 中的 sprintf"。
作为左值,keys
允许您增加为给定哈希分配的哈希桶数量。如果您知道哈希将变得很大,这可以提高效率。(这类似于通过将更大的数字分配给 $#array 来预先扩展数组。)如果您说
keys %hash = 200;
那么 %hash
将至少分配 200 个桶。即使您执行 %hash = ()
,这些桶也会保留;如果您想在 %hash
仍在作用域内时释放存储空间,请使用 undef %hash
。您不能使用 keys
以这种方式缩小为哈希分配的桶的数量(但您不必担心意外地这样做,因为尝试这样做不会有任何效果)。
您现在可以在控制结构(例如)的控制表达式中使用 my()(带或不带括号)
while (defined(my $line = <>)) {
$line = lc $line;
} continue {
print $line;
}
if ((my $answer = <STDIN>) =~ /^y(es)?$/i) {
user_agrees();
} elsif ($answer =~ /^n(o)?$/i) {
user_disagrees();
} else {
chomp $answer;
die "`$answer' is neither `yes' nor `no'";
}
此外,您可以通过在前面加上“my”来将 foreach 循环控制变量声明为词法变量。例如,在
foreach my $i (1, 2, 3) {
some_function();
}
$i 是一个词法变量,$i 的作用域扩展到循环结束,但不会超出循环结束。
请注意,您仍然不能在全局标点符号变量(如 $_ 等)上使用 my()。
新的格式 'w' 表示一个 BER 压缩整数(如 ASN.1 中定义)。它的格式是一系列一个或多个字节,每个字节提供总值的七位,最高有效位在前。每个字节的第八位都被设置,除了最后一个字节,它的第八位被清除。
如果 'p' 或 'P' 被赋予 undef 作为值,它们现在会生成一个 NULL 指针。
pack() 和 unpack() 现在在它们的模板包含无效类型时都会失败。(以前会忽略无效类型。)
新的 sysseek() 运算符是 seek() 的变体,它使用 lseek(2) 系统调用来设置和获取文件的系统读/写位置。它是使用 sysread() 或 syswrite() 之前进行查找的唯一可靠方法。它的返回值是新位置,或者在失败时是未定义的值。
如果 use
的第一个参数是一个数字,它将被视为版本号而不是模块名称。如果 Perl 解释器的版本小于 VERSION,则会打印一条错误消息,并且 Perl 会立即退出。由于 use
发生在编译时,因此此检查会在编译过程的开始立即进行,与 require VERSION
不同,后者要等到运行时才会进行检查。如果您需要在 use
库模块之前检查当前的 Perl 版本,这通常很有用,因为这些库模块在 Perl 的旧版本中发生了不兼容的更改。(我们尽量避免这样做。)
如果 VERSION 参数出现在 Module 和 LIST 之间,则 use
将使用给定的版本作为参数调用类 Module 中的 VERSION 方法。从 UNIVERSAL 类继承的默认 VERSION 方法,如果给定的版本大于变量 $Module::VERSION 的值,则会发出错误信息。(请注意,VERSION 后面没有逗号!)
这种版本检查机制类似于当前在 Exporter 模块中使用的机制,但它更快,可以与不使用 Exporter 的模块一起使用。这是新代码的推荐方法。
返回函数的原型字符串(如果函数没有原型,则返回 undef
)。FUNCTION 是要检索原型的函数的引用或名称。(实际上不是新的;只是以前从未记录过。)
srand
的默认种子,以前是 time
,已经改变。现在它是一个难以预测的系统相关值的混合,对于大多数日常用途来说应该足够了。
在 5.004 版本之前,在调用 srand
之前调用 rand
会在大多数或所有机器上产生相同的随机数序列。现在,当 Perl 看到你正在调用 rand
并且还没有调用 srand
时,它会使用默认种子调用 srand
。当然,如果你的代码可能在 5.004 之前的系统上运行,或者如果你想要一个与默认值不同的种子,你仍然应该手动调用 srand
。
骆驼书中记录的默认使用 $_ 的函数现在确实如此,并且所有这些函数都在 perlfunc 中进行了记录。
m//gc
不会在失败时重置搜索位置m//g
匹配迭代构造始终在匹配失败时重置其目标字符串的搜索位置(可以通过 pos
运算符查看);因此,在失败后的下一个 m//g
匹配从字符串的开头重新开始。在 Perl 5.004 中,可以通过添加 "c"(表示 "continue")修饰符来禁用此重置,即 m//gc
。此功能与 \G
零宽度断言相结合,使得将匹配链接在一起成为可能。参见 perlop 和 perlre。
m//x
忽略 ?*+{} 之前的空格m//x
构造一直旨在忽略所有未转义的空格。但是,在 Perl 5.004 之前,空格会转义重复修饰符,如 "*" 或 "?";例如,/a *b/x
被(错误地)解释为 /a\*b/x
。此错误已在 5.004 中修复。
sub{}
闭包现在可以工作了在 5.004 版本之前,嵌套的匿名函数无法正常工作。现在可以了。
就像包含改变的词法变量(例如 foreach
循环的词法索引变量)的匿名函数一样,格式现在可以正常工作。例如,这在以前会静默失败(只打印零),但现在没问题了
my $i;
foreach $i ( 1 .. 10 ) {
write;
}
format =
my i is @#
$i
.
但是,如果 foreach
在子例程中,它仍然会失败(没有警告)
my $i;
sub foo {
foreach $i ( 1 .. 10 ) {
write;
}
}
foo;
format =
my i is @#
$i
.
UNIVERSAL
包自动包含以下方法,这些方法被所有其他类继承
如果其对象被祝福到 CLASS
的子类中,则 isa
返回 true
isa
也可以导出,并且可以作为带有两个参数的子例程调用。这允许检查引用指向什么。例如
use UNIVERSAL qw(isa);
if(isa($ref, 'ARRAY')) {
...
}
can
检查其对象是否具有名为 METHOD
的方法,如果有,则返回对子例程的引用;如果没有,则返回 undef。
VERSION
返回类的(包的)版本号。如果给出了 NEED 参数,它将检查当前版本(由给定包中的 $VERSION 变量定义)是否不小于 NEED;如果不是这种情况,它将死亡。此方法通常作为类方法调用。此方法由 use
的 VERSION
形式自动调用。
use A 1.2 qw(some imported subs);
# implies:
A->VERSION(1.2);
注意: can
直接使用 Perl 的内部代码进行方法查找,而 isa
使用非常类似的方法和缓存策略。如果 Perl 代码在任何包中动态更改 @ISA,这可能会导致奇怪的效果。
您可以通过 Perl 或 XS 代码将其他方法添加到 UNIVERSAL 类。您不需要 use UNIVERSAL
才能使这些方法对您的程序可用。这只有在您希望在当前包中将 isa
作为普通子例程使用时才需要。
有关其他类型的 tie(),请参阅 perltie。
这是类的构造函数。这意味着它应该返回某种类型的对象。引用可以用来保存一些内部信息。
sub TIEHANDLE {
print "<shout>\n";
my $i;
return bless \$i, shift;
}
每次将绑定的句柄打印到时,都会触发此方法。除了它自己的引用之外,它还期望传递给 print 函数的列表。
sub PRINT {
$r = shift;
$$r++;
return print join( $, => map {uc} @_), $\;
}
当使用printf()
函数打印绑定句柄时,将触发此方法。除了自身引用之外,它还期望传递给printf函数的格式和列表。
sub PRINTF {
shift;
my $fmt = shift;
print sprintf($fmt, @_)."\n";
}
当通过read
或sysread
函数从句柄中读取数据时,将调用此方法。
sub READ {
$r = shift;
my($buf,$len,$offset) = @_;
print "READ called, \$buf=$buf, \$len=$len, \$offset=$offset";
}
当从句柄中读取数据时,将调用此方法。当没有更多数据时,该方法应返回undef。
sub READLINE {
$r = shift;
return "PRINT called $$r times\n"
}
当调用getc
函数时,将调用此方法。
sub GETC { print "Don't GETC, Get Perl"; return "a"; }
与其他类型的绑定一样,当绑定句柄即将被销毁时,将调用此方法。这对于调试和清理很有用。
sub DESTROY {
print "</shout>\n";
}
如果perl使用perl发行版中包含的malloc编译(即,如果perl -V:d_mymalloc
为'define'),那么可以通过以下方式运行Perl来在运行时打印内存统计信息
env PERL_DEBUG_MSTATS=2 perl your_script_here
值为2表示在编译后和退出时打印统计信息;值为1,则仅在退出时打印统计信息。(如果您想在任意时间获取统计信息,则需要安装可选的模块Devel::Peek。)
malloc.c识别三个新的编译标志。(如果perl使用系统malloc()编译,它们将不起作用。)
如果定义了此宏,则内存不足不一定是致命错误:可以通过将值分配给特殊变量$^M
来分配内存池。请参阅"$^M"。
Perl 的内存分配是通过桶进行的,桶的大小接近 2 的幂。由于这些原因,malloc 的开销可能很大,特别是对于大小正好为 2 的幂的数据。如果定义了 PACK_MALLOC
,perl 会对小分配(最多 64 字节长)使用稍微不同的算法,这使得对于 2 的幂的分配(并且经常出现)的开销可以低至 1 字节。
对于典型的 Perl 使用,预期的内存节省(在 alignbytes
中使用 8 字节对齐)约为 20%。由于额外的 malloc 开销,预期的速度下降为百分比的几分之一(难以衡量,因为节省的内存会影响速度)。
与 PACK_MALLOC
类似,此宏改进了大小接近 2 的幂的数据的分配;但它适用于大分配(默认情况下从 16K 开始)。这种分配对于大型哈希和专用脚本很常见,尤其是图像处理。
在最近的系统上,perl 为 1M 分配而从系统中请求 2M 的事实不会影响执行速度,因为这种块的尾部不会被触碰(因此不需要实际内存)。但是,这可能会导致过早的内存不足错误。因此,如果您要操作大小接近 2 的幂的非常大的块,定义此宏将是明智之举。
预期的内存节省为 0-100%(在需要这种 2**n 块的大部分内存的应用程序中为 100%);预期的速度下降可以忽略不计。
具有空原型并且除了返回固定值之外什么也不做的函数现在被内联(例如 sub PI () { 3.14159 }
)。
每个唯一的哈希键只分配一次,无论有多少个哈希具有包含该键的条目。因此,即使您有 100 个相同哈希的副本,哈希键也不需要重新分配。
对以下操作系统的支持是 Perl 5.004 中的新增功能。
Perl 5.004 现在包含了在 Windows NT 下构建“原生”perl 的支持,使用 Microsoft Visual C++ 编译器(版本 2.0 及以上)或 Borland C++ 编译器(版本 5.02 及以上)。生成的 perl 可以用于 Windows 95(如果它安装在与 Windows NT 中安装的相同目录位置)。此端口包括对 perl 扩展构建工具的支持,例如 ExtUtils::MakeMaker 和 h2xs,因此现在可以在 Windows NT 下轻松构建 Comprehensive Perl Archive Network (CPAN) 上提供的许多扩展。有关 CPAN 的更多信息,请访问 https://perldotcom.perl5.cn/,有关如何开始构建此端口的更多详细信息,请参阅 perl 发行版中的 README.win32。
还支持在 Cygwin32 环境下构建 perl。Cygwin32 是一组 GNU 工具,通过提供一个类似 Unix 的编译和执行接口,使在 Windows NT 下编译和运行许多 Unix 程序成为可能。有关此端口和如何获取 Cygwin32 工具包的更多详细信息,请参阅 perl 发行版中的 README.cygwin32。
请参阅 perl 发行版中的 README.plan9。
请参阅 perl 发行版中的 README.qnx。
请参阅 perl 发行版中的 README.amigaos。
存在六个新的实用模块
将 require MODULE
推迟到有人调用指定的子例程(这些子例程必须由 MODULE 导出)为止。此 pragma 应谨慎使用,并且仅在必要时使用。
从 dir(或当前目录)开始,向上搜索五个级别的父目录,查找类似 MakeMaker 的 'blib' 目录结构。
旨在与命令行一起使用 -M 选项,作为一种测试针对未安装版本的包的任意脚本的方法。
提供了一个方便的接口来创建编译时常量,请参阅 "perlsub 中的常量函数"。
告诉编译器启用(或禁用)对内置操作使用 POSIX 本地化。
当 use locale
生效时,当前的 LC_CTYPE 区域设置将用于正则表达式和大小写映射;LC_COLLATE 用于字符串排序;LC_NUMERIC 用于 printf 和 sprintf 中的数字格式化(但不在 print 中)。LC_NUMERIC 始终在 write 中使用,因为格式的词法作用域充其量是有问题的。
每个 use locale
或 no locale
都会影响语句,直到封闭的 BLOCK 的末尾,或者如果没有在 BLOCK 内,则影响到当前文件的末尾。区域设置可以使用 POSIX::setlocale() 切换和查询。
有关更多信息,请参见 perllocale。
在编译 Perl 代码时禁用不安全的操作码或任何命名的操作码。
启用 VMS 特定的语言功能。目前,有三个 VMS 特定的功能可用:'status',它使 $?
和 system
返回真正的 VMS 状态值,而不是模拟 POSIX;'exit',它使 exit
接受真正的 VMS 状态值,而不是假设 exit 1
是错误;以及 'time',它使所有时间相对于本地时区,遵循 VMS 传统。
虽然 Perl 5.004 与几乎所有与 Perl 5.003 一起使用的模块兼容,但有一些例外。
Module Required Version for Perl 5.004
------ -------------------------------
Filter Filter-1.12
LWP libwww-perl-5.08
Tk Tk400.202 (-w makes noise)
此外,majordomo 邮件列表程序版本 1.94.1 不适用于 Perl 5.004(也不适用于 perl 4),因为它执行了无效的正则表达式。此错误在 majordomo 版本 1.94.2 中已修复。
installperl 脚本现在将扩展的 Perl 源文件放置在特定于体系结构的库目录中,该目录一直是扩展的共享库所在的位置。此更改旨在允许管理员将 Perl 5.004 库目录保持为与先前版本相同,而不会冒扩展的 Perl 源代码和共享库之间出现二进制不兼容的风险。
全新的模块,按主题而不是严格按字母顺序排列
CGI.pm Web server interface ("Common Gateway Interface")
CGI/Apache.pm Support for Apache's Perl module
CGI/Carp.pm Log server errors with helpful context
CGI/Fast.pm Support for FastCGI (persistent server process)
CGI/Push.pm Support for server push
CGI/Switch.pm Simple interface for multiple server types
CPAN Interface to Comprehensive Perl Archive Network
CPAN::FirstTime Utility for creating CPAN configuration file
CPAN::Nox Runs CPAN while avoiding compiled extensions
IO.pm Top-level interface to IO::* classes
IO/File.pm IO::File extension Perl module
IO/Handle.pm IO::Handle extension Perl module
IO/Pipe.pm IO::Pipe extension Perl module
IO/Seekable.pm IO::Seekable extension Perl module
IO/Select.pm IO::Select extension Perl module
IO/Socket.pm IO::Socket extension Perl module
Opcode.pm Disable named opcodes when compiling Perl code
ExtUtils/Embed.pm Utilities for embedding Perl in C programs
ExtUtils/testlib.pm Fixes up @INC to use just-built extension
FindBin.pm Find path of currently executing program
Class/Struct.pm Declare struct-like datatypes as Perl classes
File/stat.pm By-name interface to Perl's builtin stat
Net/hostent.pm By-name interface to Perl's builtin gethost*
Net/netent.pm By-name interface to Perl's builtin getnet*
Net/protoent.pm By-name interface to Perl's builtin getproto*
Net/servent.pm By-name interface to Perl's builtin getserv*
Time/gmtime.pm By-name interface to Perl's builtin gmtime
Time/localtime.pm By-name interface to Perl's builtin localtime
Time/tm.pm Internal object for Time::{gm,local}time
User/grent.pm By-name interface to Perl's builtin getgr*
User/pwent.pm By-name interface to Perl's builtin getpw*
Tie/RefHash.pm Base class for tied hashes with references as keys
UNIVERSAL.pm Base class for *ALL* classes
现在支持现有 Fcntl 模块中的新常量,前提是您的操作系统碰巧支持它们。
F_GETOWN F_SETOWN
O_ASYNC O_DEFER O_DSYNC O_FSYNC O_SYNC
O_EXLOCK O_SHLOCK
这些常量旨在与 Perl 运算符 sysopen() 和 fcntl() 以及基本数据库模块(如 SDBM_File)一起使用。有关这些常量和其他 Fcntl 常量的确切含义,请参阅您操作系统的 fcntl() 和 open() 文档。
此外,Fcntl 模块现在提供以下常量供 Perl 运算符 flock() 使用。
LOCK_SH LOCK_EX LOCK_NB LOCK_UN
这些常量在所有环境中都有定义(因为在没有 flock() 系统调用的地方,Perl 会模拟它)。但是,出于历史原因,除非使用 ":flock" 标签显式请求(例如 use Fcntl ':flock'
),否则这些常量不会被导出。
IO 模块提供了一种简单的机制,可以一次性加载所有 IO 模块。目前这包括
IO::Handle
IO::Seekable
IO::File
IO::Pipe
IO::Socket
有关这些模块的更多信息,请参阅其各自的文档。
Math::Complex 模块已被完全重写,现在支持更多操作。这些是重载的
+ - * / ** <=> neg ~ abs sqrt exp log sin cos atan2 "" (stringify)
现在导出以下函数
pi i Re Im arg
log10 logn ln cbrt root
tan
csc sec cot
asin acos atan
acsc asec acot
sinh cosh tanh
csch sech coth
asinh acosh atanh
acsch asech acoth
cplx cplxe
这个新模块为那些只需要对实数使用三角函数的人提供了 Math::Complex 的更简单接口。
DB_File 已经做了很多改变。以下是一些亮点
修复了一些错误。
根据公众需求,添加了对标准哈希函数 exists() 的支持。
使其与 Berkeley DB 1.86 兼容。
使负下标与 RECNO 接口一起使用。
将默认标志从 O_RDWR 更改为 O_CREAT|O_RDWR,将默认模式从 0640 更改为 0666。
如果可用,DB_File 会自动从 Fcntl 导入 open() 常量(O_RDWR、O_CREAT 等)。
更新了文档。
有关更改的完整列表,请参阅 DB_File.pm 中的 HISTORY 部分。自 5.003 以来,DB_File 1.01 之后的所有内容都已添加。
主要重写 - 添加了对 udp 回声和真实 icmp ping 的支持。
许多返回列表的 Perl 内置函数现在都有面向对象的重写。这些是
File::stat
Net::hostent
Net::netent
Net::protoent
Net::servent
Time::gmtime
Time::localtime
User::grent
User::pwent
例如,您现在可以这样说
use File::stat;
use User::pwent;
$his = (stat($filename)->st_uid == pwent($whoever)->pw_uid);
Perl 5.004 中包含的 pod2html 实用程序是全新的。默认情况下,它将转换后的 HTML 发送到其标准输出,而不是像 Perl 5.003 的 pod2html 那样写入文件。使用 --outfile=FILENAME 选项写入文件。
void
XSUB 现在默认不返回值由于早期 Perl 版本中的文档/实现错误,返回值类型为 void
的 XSUB 实际上会返回一个值。通常该值为 XSUB 的 GV,但有时它可能是某个已释放或重用的值,这有时会导致程序失败。
在 Perl 5.004 中,如果一个 XSUB 被声明为返回 void
,它实际上不返回值,即返回一个空列表(尽管存在一个向后兼容的例外;见下文)。如果您的 XSUB 确实返回一个 SV,您应该将其返回值类型指定为 SV *
。
为了向后兼容,xsubpp 尝试猜测一个 void
XSUB 到底是 void
还是想要返回一个 SV *
。它通过检查 XSUB 的文本内容来实现:如果 xsubpp 发现类似于对 ST(0)
的赋值,它会假设 XSUB 的返回值类型实际上是 SV *
。
gv_fetchmethod
和 perl_call_sv
gv_fetchmethod
函数查找对象的某个方法,就像在 Perl 5.003 中一样。它返回的 GV 可能是一个方法缓存条目。但是,在 Perl 5.004 中,方法缓存条目对用户不可见;因此,它们不能再直接传递给 perl_call_sv
。相反,您应该在 GV 上使用 GvCV
宏来提取其 CV,并将 CV 传递给 perl_call_sv
。
将 gv_fetchmethod
的结果传递给 perl_call_sv
最有可能的症状是 Perl 在对给定方法的第二次调用时产生“未定义的子程序调用”错误(因为第一次调用没有缓存)。
perl_eval_pv
一个新的函数,方便在 C 代码中对 Perl 代码字符串进行 eval。此函数返回 eval 语句的值,可以用来代替从符号表中获取全局变量。有关详细信息和示例,请参见 perlguts、perlembed 和 perlcall。
哈希键的内部处理方式已更改。旧的哈希表 API 仍然完全受支持,并且很可能将继续保持支持。对 API 的添加允许将键作为 SV*
传递,以便 tied
哈希可以被赋予真正的标量作为键,而不是简单的字符串(非 tied
哈希仍然只能使用字符串作为键)。如果新的扩展想要使用 SV*
键,则必须使用新的哈希访问函数和宏。这些添加也使得操作 HE*
(哈希条目)变得可行,这可能更高效。有关详细信息,请参见 perlguts。
许多基础和库 pod 进行了更新。这些新 pod 包含在第 1 部分中。
本文件。
常见问题解答。
区域设置支持(国际化和本地化)。
Perl 面向对象编程教程。
Perl 内部 IO 抽象接口。
Perl 模块库和模块创建的推荐实践。从 perlmod 中提取(因此变得更小)。
虽然不是新的,但它已经进行了大规模更新。
虽然不是新的,但它已经进行了大规模更新。
一些新的条件将触发以前静默的警告。有些只影响某些平台。以下新的警告和错误概述了这些。这些消息按以下分类(按绝望程度递增排列)
(W) A warning (optional).
(D) A deprecation (optional).
(S) A severe warning (mandatory).
(F) A fatal error (trappable).
(P) An internal error you should never see (trappable).
(X) A very fatal error (nontrappable).
(A) An alien error message (not generated by Perl).
(W) 在同一作用域中重新声明了词法变量,有效地消除了对先前实例的所有访问。这几乎总是打字错误。请注意,早期变量将一直存在到作用域结束或所有闭包引用被销毁为止。
(F) delete() 的参数必须是哈希元素,例如
$foo{$bar}
$ref->[12]->{"susie"}
或哈希切片,例如
@foo{$bar, $baz, $xyzzy}
@{$ref->[12]}{"susie", "queue"}
(X) 在 MS-DOS 机器上,您无法分配超过 64K 的内存。
(F) 您无法分配超过 2^31+"少量" 字节的内存。
(W) 模式匹配 (//)、替换 (s///) 和音译 (tr///) 运算符作用于标量值。如果您将其中一个运算符应用于数组或哈希,它将把数组或哈希转换为标量值(数组的长度或哈希的元素数量),然后对该标量值进行操作。这可能不是您想要做的。请参阅 "perlfunc 中的 grep" 和 "perlfunc 中的 map" 以了解替代方法。
(P) Perl 维护一个引用计数的内部字符串表,以优化哈希键和其他字符串的存储和访问。这表明有人尝试减少一个字符串的引用计数,而该字符串在表中已无法找到。
(W) 您将引用作为第一个参数传递给用作左值的 substr(),这很奇怪。也许您忘记了先解除引用。请参阅 "perlfunc 中的 substr"。
(W) 您使用了 Foo::
形式的限定裸字,但编译器在该点之前没有看到该命名空间的其他使用。也许您需要预先声明一个包?
(F) Perl 优化了排序子例程的内部处理,并保留了指向它们的指针。您尝试在当前活动时重新定义一个这样的排序子例程,这是不允许的。如果您真的想这样做,您应该编写 sort { &func } @x
而不是 sort func @x
。
(F) "strict refs" 只允许硬引用。符号引用是不允许的。请参阅 perlref。
(P) 内部错误,尝试解析由方法名(而不是子例程引用)指定的重载。
(S) 您重新定义了一个以前有资格内联的子例程。请参阅 "perlsub 中的常量函数" 以了解评论和解决方法。
(S) 您取消定义了一个以前有资格内联的子例程。请参阅 "perlsub 中的常量函数" 以了解评论和解决方法。
(F) 重载“=”的方法有错误。请参阅 "overload" 中的“Copy Constructor”。
(F) 您传递给 die() 的是一个空字符串(相当于 die ""
),或者您在没有参数的情况下调用它,而 $@
和 $_
都为空。
(W) 您正在通过非常规方式退出一个特殊的块结构(例如排序块或子例程),例如 goto 或循环控制语句。请参阅 "perlfunc" 中的 "sort"。
(F) Perl 将标识符(变量、函数等的名称)限制为 252 个字符(对于简单名称),对于复合名称(例如 $A::B
)则略多。您已超过 Perl 的限制。未来的 Perl 版本可能会消除这些任意限制。
(F) 在输入中发现了一个回车符。这是一个错误,而不是警告,因为回车符会破坏多行字符串,包括 here 文档(例如,print <<EOF;
)。
(X) PERL5OPT 环境变量只能用于设置以下开关:-[DIMUdmw]。
(S) 您指定的十六进制数字文字对于您的架构来说太大了。在 32 位架构上,最大的十六进制文字是 0xFFFFFFFF。
(S) 您指定的八进制数字文字对于您的架构来说太大了。在 32 位架构上,最大的八进制文字是 037777777777。
(P) 用于glob
和<*.c>
的外部程序出现问题。这可能意味着您的csh(C shell)已损坏。如果是这样,您应该更改config.sh中的所有与csh相关的变量:如果您有tcsh,请将变量设置为引用它,就像它是csh一样(例如full_csh='/usr/bin/tcsh'
);否则,将它们全部清空(除了d_csh
应该为'undef'
),这样Perl就会认为csh不存在。无论哪种情况,在编辑config.sh后,运行./Configure -S
并重新构建Perl。
(W) Perl 不理解给定的格式转换。请参阅 "perlfunc 中的 sprintf"。
(F) 给定的字符不是有效的 pack 类型。请参阅 "perlfunc 中的 pack"。
(F) 给定的字符不是有效的 unpack 类型。请参阅 "perlfunc 中的 unpack"。
(W) 拼写错误通常表现为唯一的变量名。如果您有充分的理由使用唯一的名称,那么只需再次提及它以抑制消息(use vars
准则就是为此目的提供的)。
(F) formline 的第一个参数必须是有效的格式图片规范。它被发现为空,这可能意味着您提供了一个未初始化的值。请参阅 perlform。
(F) 您尝试使用指向缓冲区外部的偏移量进行读/写/发送/接收操作。这很难想象。唯一的例外是,sysread()
超出缓冲区将扩展缓冲区并用零填充新区域。
(X|F) malloc() 函数返回 0,表示没有足够的剩余内存(或虚拟内存)来满足请求。
请求被认为很小,因此捕获它的可能性取决于 Perl 的编译方式。默认情况下它不可捕获。但是,如果为此编译,Perl 可能会在使用此消息进行 die() 后使用 $^M
的内容作为紧急池。在这种情况下,错误可以捕获一次。
(F) malloc() 函数返回 0,表示没有足够的剩余内存(或虚拟内存)来满足请求。但是,请求被判断为足够大(编译时默认值为 64K),因此允许通过捕获此错误来关闭程序。
(P) 库函数 frexp() 失败,导致 printf("%f") 无法执行。
(W) qw() 列表包含由空格分隔的项目;与文字字符串一样,注释字符不会被忽略,而是被视为文字数据。(您可能使用了与这里显示的括号不同的分隔符;花括号也经常使用。)
您可能写了类似这样的代码
@list = qw(
a # a comment
b # another comment
);
而您应该写成这样
@list = qw(
a
b
);
如果您确实需要注释,请使用传统的方式构建列表,使用引号和逗号
@list = (
'a', # a comment
'b', # another comment
);
(W) qw() 列表包含由空格分隔的项目;因此,不需要逗号来分隔项目。(您可能使用了与这里显示的括号不同的分隔符;花括号也经常使用。)
您可能写了类似这样的代码
qw! a, b, c !;
这会将文字逗号放入一些列表项中。如果您不希望逗号出现在数据中,请在没有逗号的情况下编写代码
qw! a b c !;
(W) 您使用哈希切片(由 @ 表示)来选择哈希中的单个元素。通常最好请求标量值(由 $ 表示)。区别在于 $foo{&bar}
在赋值时和评估其参数时始终表现为标量,而 @foo{&bar}
在赋值时表现为列表,并为其下标提供列表上下文,如果您只期望一个下标,这可能会导致奇怪的行为。
(P) 通过导入存根可能会破坏 @ISA 树上的重载解析。存根永远不应该被隐式创建,但对 can
的显式调用可能会破坏这一点。
(X) Perl 脚本中的 #! 行(或本地等效项)包含 **-T** 选项,但 Perl 在其参数列表中没有使用 **-T** 选项调用。这是一个错误,因为当 Perl 在脚本中发现 **-T** 时,已经太迟了,无法从环境中正确地标记所有内容。因此 Perl 放弃了。
(W) 当调用 untie
时,从 tie
(或 tied
)返回的对象的副本仍然有效。
(F) Perl 解析器不知道如何处理 Perl 脚本(或 eval)中指定的字符。您可能尝试运行压缩脚本、二进制程序或目录作为 Perl 程序。
(F) 您版本的可执行文件不支持 fork。
请注意,在某些系统(如 OS/2)下,可能存在不同版本的 Perl 可执行文件,其中一些可能支持 fork,而另一些则不支持。尝试更改您调用的 Perl 的名称,例如 perl_
、perl__
等。
(D) 5.004 之前的 Perl 版本错误地解释了任何类型标记后跟 "$" 和数字。例如,"$$0" 被错误地解释为 "${$}0" 而不是 "${$0}"。此错误在 Perl 5.004 中(大部分)已修复。
但是,Perl 5.004 的开发人员无法完全修复此错误,因为至少有两个广泛使用的模块依赖于字符串中 "$$0" 的旧含义。因此,Perl 5.004 仍然以旧的(错误的)方式在字符串内部解释 "$$<digit>";但它会生成此消息作为警告。在 Perl 5.005 中,这种特殊处理将停止。
(W) 在条件表达式中,您使用了 <HANDLE>、<*>(glob)、each()
或 readdir()
作为布尔值。这些构造中的每一个都可以返回 "0" 的值;这将使条件表达式为假,这可能不是您的本意。当在条件表达式中使用这些构造时,请使用 defined
运算符测试它们的值。
(W) 一个内部(嵌套)的匿名子程序位于一个命名子程序内部,而另一个子程序位于其外部;匿名(最内层)子程序引用了最外层子程序中定义的词法变量。例如
sub outermost { my $a; sub middle { sub { $a } } }
如果匿名子程序从最外层子程序调用或引用(直接或间接),它将像预期的那样共享变量。但如果在最外层子程序未激活时调用或引用匿名子程序,它将看到共享变量的值,该值与第一次调用最外层子程序之前和期间的值相同,这可能不是你想要的。
在这种情况下,通常最好使用sub {}
语法使中间子程序匿名。Perl 对嵌套匿名子程序中的共享变量有专门的支持;中间的命名子程序会干扰此功能。
(W) 一个内部(嵌套)的命名子程序引用了外部子程序中定义的词法变量。
当调用内部子程序时,它可能会看到外部子程序变量的值,该值与第一次调用外部子程序之前和期间的值相同;在这种情况下,在第一次调用外部子程序完成后,内部和外部子程序将不再共享该变量的公共值。换句话说,该变量将不再共享。
此外,如果外部子程序是匿名的并引用了其外部的词法变量,那么外部和内部子程序将永远不会共享给定变量。
这个问题通常可以通过使用sub {}
语法使内部子程序匿名来解决。当调用或引用引用外部子程序中变量的内部匿名子程序时,它们会自动重新绑定到这些变量的当前值。
(W) 您传递给 warn() 的是一个空字符串(等同于 warn ""
),或者您在没有参数的情况下调用它,而 $_
为空。
(W) 这是 VMS 特有的警告。在准备迭代 %ENV 时,遇到了一个逻辑名称,它违反了逻辑名称的语法规则。由于它无法正常转换,因此被跳过,不会出现在 %ENV 中。这可能是一个良性事件,因为某些软件包可能会直接修改逻辑名称表并引入非标准名称,或者它可能表明逻辑名称表已损坏。
(P) 这是 OS/2 特有的错误。很可能您正在使用过时的 Perl 版本,这种情况不应该发生。
(F) 这是 OS/2 特有的错误。PERLLIB_PREFIX 应采用以下形式:
prefix1;prefix2
或
prefix1 prefix2
其中 prefix1 和 prefix2 不为空。如果 prefix1
确实是内置库搜索路径的前缀,则会替换 prefix2。如果找不到组件或组件过长,则可能会出现此错误。请参阅 README.os2 中的“PERLLIB_PREFIX”。
(F) 这是 OS/2 特有的错误。PERL_SH_DIR 是查找 sh
-shell 的目录。请参阅 README.os2 中的“PERL_SH_DIR”。
(W) 这是 OS/2 应用程序发出的标准消息,而 *nix 应用程序会静默退出。这被认为是 OS/2 移植的一个特性。可以通过适当的信号处理程序轻松禁用此功能,请参阅 "perlipc 中的信号"。另请参阅 README.os2 中的“进程被 SIGTERM/SIGINT 终止”。
如果您发现您认为是错误,您可能需要检查 comp.lang.perl.misc 新闻组中最近发布的文章的标题。您也可以在 Perl 主页 https://perldotcom.perl5.cn/perl/ 上找到相关信息。
如果您认为您遇到了未报告的错误,请运行随您的发行版提供的 perlbug 程序。确保将您的错误缩减为一个微小但足够的测试用例。您的错误报告以及 perl -V
的输出将被发送到 <[email protected]>,由 Perl 移植团队进行分析。
有关更改的详细信息,请参阅Changes文件。
有关如何构建 Perl 的说明,请参阅INSTALL文件。该文件已针对 5.004 版本进行了重大更新,即使是经验丰富的用户也应该仔细阅读。
有关一般事项,请参阅README文件。
有关版权信息,请参阅Copying文件。
由 Tom Christiansen 构建,从无数贡献者那里获得材料(经许可),并由多个 Perl 移植者进行评审。
最后更新时间:1997 年 5 月 14 日星期三 11:14:09 EDT