内容

名称

perl5140delta - perl v5.14.0 的新增内容

描述

本文档描述了 5.12.0 版本和 5.14.0 版本之间的差异。

如果您要从 5.10.0 等早期版本升级,请先阅读 perl5120delta,其中描述了 5.10.0 和 5.12.0 之间的差异。

此版本中的一些错误修复已移植到 5.12.x 的后续版本。这些修复在括号中用 5.12.x 版本表示。

注意

perlpolicy 中所述,Perl 5.14.0 的发布标志着 Perl 5.10 支持的正式结束。Perl 5.10 或更早版本的用户应考虑升级到更新版本的 Perl。

核心增强功能

Unicode

Unicode 版本 6.0 现已支持(大部分)

Perl 附带了 Unicode 6.0 数据库,该数据库已使用 勘误表 #8 更新,但有一个例外,如下所述。有关新版本的详细信息,请参阅 http://unicode.org/versions/Unicode6.0.0/。Perl 不支持任何 Unicode 临时属性,包括此版本中的新属性。

Unicode 6.0 选择使用名称 BELL 来表示 U+1F514 处的字符,该字符看起来像一个铃铛,在日本手机中使用。这与 Perl 长期以来将 BELL 作为 ASCII BEL 字符(U+0007)的用法冲突。在 Perl 5.14 中,\N{BELL} 仍然表示 U+0007,但其使用会生成弃用警告消息,除非此类警告被关闭。U+0007 在 Perl 中的新名称是 ALERT,这与它的现有简写序列 "\a" 很好地对应。\N{BEL} 表示 U+0007,不会发出警告。U+1F514 处的字符在 5.14 中没有名称,但可以通过 \N{U+1F514} 来引用。在 Perl 5.16 中,\N{BELL} 将引用 U+1F514;所有使用 \N{BELL} 的代码都应该在升级之前转换为使用 \N{ALERT}\N{BEL}"\a"

use feature 'unicode_strings' 的完整功能

此版本为 use feature 'unicode_strings' 提供了完整的功能。在其作用域下,执行的所有字符串操作和编译的正则表达式(即使在作用域之外执行)都具有 Unicode 语义。请参阅 "feature 中的 'unicode_strings' 特性"。但是,请参阅下面的 "反向括号字符类和多字符折叠"

此特性避免了大多数形式的“Unicode 错误”(有关详细信息,请参阅 "perlunicode 中的“Unicode 错误”")。如果您的代码有可能处理 Unicode 字符串,强烈建议您使用此子pragma 以避免出现意外情况。

\N{NAME}charnames 增强功能

有关所有这些更改的详细信息,请参阅 charnames

针对有问题的(非)Unicode 代码点的新的警告类别。

添加了三个新的“utf8”警告子类别。这些允许您关闭一些“utf8”警告,同时允许其他警告保持开启。这三个类别是:当遇到 UTF-16 代理时为 surrogate;当遇到 Unicode 非字符代码点时为 nonchar;当遇到超过 0x10FFFF 的合法 Unicode 最大值的代码点时为 non_unicode

任何无符号值都可以编码为字符

在此版本中,Perl 采用了一种模型,即任何无符号值都可以被视为代码点,并在内部(作为 utf8)进行编码,而不会发出警告,而不仅仅是 Unicode 中合法的代码点。但是,除非显式关闭 utf8 或相应的词法警告子类别(参见上一项),否则输出或执行 Unicode 定义的操作(例如将此类代码点大写)将生成警告。尝试使用严格规则(例如使用 :encoding(UTF-8) 层)输入这些代码点将继续失败。在此版本之前,处理不一致,并且在某些地方不正确。

Unicode 非字符,其中一些以前被 Perl 错误地认为在某些地方是非法的,与 Unicode 标准相矛盾,现在在内部始终合法。输入或输出它们的工作方式与非法的 Unicode 代码点相同,因为 Unicode 标准规定它们(仅)对于“开放交换”是非法的。

Unicode 数据库文件未安装

Unicode 数据库文件不再与 Perl 一起安装。这不会影响 Perl 中的任何功能,并节省了大量的磁盘空间。如果您需要这些文件,可以从 http://www.unicode.org/Public/zipped/6.0.0/ 下载。

正则表达式

(?^...) 结构表示默认修饰符

在正则表达式中,紧跟在 "(?" 后的 ASCII 脱字符 "^" 现在表示子表达式不继承周围的修饰符(如 /i),而是恢复为 Perl 默认值。脱字符后的任何修饰符都将覆盖默认值。

正则表达式的字符串化现在使用此符号。例如,qr/hlagh/i 以前被字符串化为 (?i-xsm:hlagh),但现在被字符串化为 (?^i:hlagh)

此更改的主要目的是允许依赖字符串化的测试不必在添加新修饰符时进行更改。请参阅 "perlre 中的扩展模式"

此更改可能会破坏将字符串化的正则表达式与包含 ?-xism 的固定字符串进行比较的代码。

/d/l/u/a 修饰符

添加了四个新的正则表达式修饰符。这些修饰符是互斥的:一次只能启用一个。

有关更多详细信息,请参阅 "perlre 中的修饰符"

非破坏性替换

替换 (s///) 和音译 (y///) 运算符现在支持 /r 选项,该选项复制输入变量,在副本上执行替换,并返回结果。原始变量保持不变。

my $old = "cat";
my $new = $old =~ s/cat/dog/r;
# $old is "cat" and $new is "dog"

这在使用 map 时特别有用。有关更多示例,请参阅 perlop

可重入正则表达式引擎

现在可以在正则表达式内的 (?{...})(??{...}) 代码块中安全地使用正则表达式。

但是,这些块仍处于实验阶段,并且在词法 (my) 变量和异常退出方面仍然存在问题。

use re '/flags'

re 准则现在能够在词法作用域结束之前打开正则表达式标志。

use re "/x";
"foo" =~ / (.+) /;  # /x implied

有关详细信息,请参阅 "re 中的'/flags' 模式"

\o{...} 用于八进制

在双引号类上下文中,有一个新的八进制转义序列 "\o"。此结构允许表示超出当前最大值 0777 的大型八进制序数。它还允许您以八进制形式指定一个字符,该字符可以安全地与其他正则表达式片段连接,并且不会被误认为是正则表达式捕获组的反向引用。请参阅 "perlre 中的捕获组"

添加 \p{Titlecase} 作为 \p{Title} 的同义词

添加此同义词是为了与 Unicode 属性名称 \p{Uppercase}\p{Lowercase} 对称。

正则表达式调试输出改进

正则表达式调试输出(通过 use re 'debug' 打开)现在在转义非 ASCII 字符时使用十六进制,而不是八进制。

delete $+{...} 的返回值

自定义正则表达式引擎现在可以确定delete%+%-条目上的返回值。

语法增强

数组和哈希容器函数接受引用

警告:此功能被认为是实验性的,因为其确切行为可能会在未来的 Perl 版本中发生变化。

所有直接操作数组或哈希容器的内置函数现在也接受对数组或哈希的未祝福硬引用

|----------------------------+---------------------------|
| Traditional syntax         | Terse syntax              |
|----------------------------+---------------------------|
| push @$arrayref, @stuff    | push $arrayref, @stuff    |
| unshift @$arrayref, @stuff | unshift $arrayref, @stuff |
| pop @$arrayref             | pop $arrayref             |
| shift @$arrayref           | shift $arrayref           |
| splice @$arrayref, 0, 2    | splice $arrayref, 0, 2    |
| keys %$hashref             | keys $hashref             |
| keys @$arrayref            | keys $arrayref            |
| values %$hashref           | values $hashref           |
| values @$arrayref          | values $arrayref          |
| ($k,$v) = each %$hashref   | ($k,$v) = each $hashref   |
| ($k,$v) = each @$arrayref  | ($k,$v) = each $arrayref  |
|----------------------------+---------------------------|

这允许这些内置函数在长解引用链或子例程的返回值上进行操作,而无需将它们包装在@{}%{}

push @{$obj->tags}, $new_tag;  # old way
push $obj->tags,    $new_tag;  # new way

for ( keys %{$hoh->{genres}{artists}} ) {...} # old way 
for ( keys $hoh->{genres}{artists}    ) {...} # new way 

单项原型

+原型是$的特殊替代方案,当给定文字数组或哈希变量时,它就像\[@%]一样,但否则会强制对参数进行标量上下文。请参阅"perlsub 中的原型"

package块语法

包声明现在可以包含代码块,在这种情况下,声明仅在该块内有效。因此,package Foo { ... }{ package Foo; ... } 完全等效。它也适用于声明中的版本号,如 package Foo 1.2 { ... },这是它最吸引人的特性。请参阅perlfunc

语句标签可以在更多地方出现

语句标签现在可以出现在任何类型的语句或声明之前,例如 package

堆叠标签

多个语句标签现在可以出现在单个语句之前。

十六进制/二进制字面量中允许使用大写 X/B

字面量现在可以使用大写 0X...0B... 前缀,除了已经支持的 0x...0b... 语法 [perl #76296]。

C、Ruby、Python 和 PHP 已经支持这种语法,它使 Perl 在内部更加一致:使用 eval sprintf "%#X", 0x10 进行往返现在返回 16,就像 eval sprintf "%#x", 0x10 一样。

可重写绑定函数

tietieduntie 现在可以被重写 [perl #75902]。

异常处理

为了提高可靠性和一致性,对 diewarn$@ 的行为进行了多项更改。

其他增强功能

在 Linux 上,$0 的赋值使用 prctl() 设置了传统的进程名称

在 Linux 上,除了通过 argv[0] 更改 POSIX 名称外,传统的进程名称现在还使用 prctl(2) 设置,正如 Perl 从 4.000 版本开始所做的那样。现在,读取传统进程名称的系统实用程序(如 pstopkillall)可以识别您在将 $0 赋值时设置的名称。您提供的字符串将在 16 个字节处被截断;此限制是由 Linux 强加的。

srand() 现在返回种子

这允许需要具有可重复结果的程序不必自己创建种子生成机制。相反,它们可以使用 srand() 并存储返回值以供将来使用。一个例子是测试程序,其组合太多,无法在每次运行的可用时间内进行全面测试。它可以每次测试一个随机子集,如果出现故障,则记录用于该运行的种子,以便稍后使用它来生成相同的结果。

printf 类函数理解 1980 年后的尺寸修饰符

Perl 的 printf 和 sprintf 运算符以及 Perl 的内部 printf 替换函数现在理解 C90 尺寸修饰符“hh”(char)、“z”(size_t)和“t”(ptrdiff_t)。此外,当使用 C99 编译器编译时,Perl 现在理解尺寸修饰符“j”(intmax_t)(但这不可移植)。

因此,例如,在任何现代机器上,sprintf("%hhd", 257) 返回“1”。

新的全局变量 ${^GLOBAL_PHASE}

添加了一个新的全局变量 ${^GLOBAL_PHASE},以允许内省 Perl 解释器的当前阶段。它在 "${^GLOBAL_PHASE}" in perlvar"BEGIN, UNITCHECK, CHECK, INIT and END" in perlmod 中有详细说明。

-d:-foo 调用 Devel::foo::unimport

语法 -d:foo 在 5.6.1 中扩展,使 -d:foo=bar 等效于 -MDevel::foo=bar,它在内部扩展为 use Devel::foo 'bar'。Perl 现在允许在模块名称前添加 -,其语义与 -M 相同;也就是说

-d:-foo

等效于 -M-Devel::foo:扩展为 no Devel::foo,如果该方法存在,则调用 Devel::foo->unimport()

-d:-foo=bar

等效于 -M-Devel::foo=bar:扩展为 no Devel::foo 'bar',如果该方法存在,则调用 Devel::foo->unimport("bar")

这对于在加载 Devel::* 模块的 import 方法以进行调试时,抑制其默认操作特别有用。

文件句柄方法调用按需加载 IO::File

当对文件句柄的某个方法调用由于无法解析该方法且未加载 IO::File 而导致死亡时,Perl 现在通过 require 加载 IO::File 并再次尝试解析方法。

open my $fh, ">", $file;
$fh->binmode(":raw");     # loads IO::File and succeeds

这也适用于诸如 STDOUTSTDERRSTDIN 之类的全局变量。

STDOUT->autoflush(1);

由于这种按需加载仅在方法解析失败时才会发生,因此手动加载 IO::File 父类以获得部分方法支持的传统方法仍然按预期工作。

use IO::Handle;
open my $fh, ">", $file;
$fh->autoflush(1);        # IO::File not loaded

改进的 IPv6 支持

Socket 模块为 IPv6 提供了新的功能,包括 Socket::getaddrinfo()Socket::getnameinfo() 函数的实现,以及相关的常量和一些新函数。请参阅 Socket

DTrace 探针现在包含包名

DTrace 探针现在包含一个额外的参数 arg3,其中包含正在进入或离开的子程序的编译包。

例如,使用以下 DTrace 脚本

perl$target:::sub-entry
{
    printf("%s::%s\n", copyinstr(arg0), copyinstr(arg3));
}

然后运行

$ perl -e 'sub test { }; test'

DTrace 将打印

main::test

新的 C API

请参阅 "内部更改"

安全

用户定义的正则表达式属性

"perlunicode 中的“用户定义字符属性”" 文档中说明,您可以通过定义以“In”或“Is”开头的子例程来创建自定义属性。但是,Perl 实际上并没有强制执行该命名限制,因此如果存在 foo::bar(),则 \p{foo::bar} 可以调用它。现在强制执行了记录的约定。

此外,Perl 不再允许受污染的正则表达式调用用户定义的属性。它只是直接报错 [perl #82616]。

不兼容的更改

Perl 5.14.0 与任何以前的稳定版本不兼容。

除了以下部分,请参阅 "C API 更改"

正则表达式和字符串转义

反转的方括号字符类和多字符折叠

在 Unicode 规则下,某些字符在 /i 正则表达式匹配中匹配两个或三个字符的序列。一个例子是 LATIN SMALL LETTER SHARP S,它匹配序列 ss

'ss' =~ /\A[\N{LATIN SMALL LETTER SHARP S}]\z/i  # Matches

但是,这会导致非常反直觉的结果,尤其是在反转时。因此,Perl 5.14 在反转的字符类中不使用多字符 /i 匹配。

'ss' =~ /\A[^\N{LATIN SMALL LETTER SHARP S}]+\z/i  # ???

这应该匹配任何不是 SHARP S 以及 SHARP S/i 下匹配的字符序列。"s" 不是 SHARP S,但 Unicode 说 "ss"SHARP S/i 下匹配的。那么哪个“获胜”?由于字符串包含 ss 导致匹配失败,还是由于包含 s 后面跟着另一个 s 导致匹配成功?

早期版本的 Perl 确实允许这种多字符匹配,但由于存在 bug,它大多不起作用。

\400-\777

在某些情况下,正则表达式中的 \400-\777 的行为与它们在所有其他类似双引号的上下文中不同。从 5.10.1 开始,Perl 在发生这种情况时发出弃用警告。现在,这些字面量在所有类似双引号的上下文中行为相同,即等效于 \x{100}-\x{1FF},并且没有弃用警告。

命令行选项 -0 中使用 \400-\777 保留其传统含义。它们会将整个输入文件读入内存;以前,这仅针对 -0777 文档化。

由于存在各种歧义,您应该使用新的 \o{...} 结构来用八进制表示字符。

大多数 \p{} 属性现在不受大小写不敏感匹配的影响

对于大多数 Unicode 属性,让它们在 /i 大小写不敏感匹配下匹配不同没有意义。这样做会导致意外结果和潜在的安全漏洞。例如

m/\p{ASCII_Hex_Digit}+/i

以前可以匹配非 ASCII 字符,因为使用了 Unicode 匹配规则(尽管存在一些错误)。现在,在 /i 下的匹配与非 /i 匹配的结果相同,除了少数几个人们期望有差异的属性,即大小写是其含义的组成部分的属性,例如 m/\p{Uppercase}/im/\p{Lowercase}/i,它们都匹配与 m/\p{Cased}/i 匹配的相同代码点。详细信息请参见 "perlrecharclass 中的 Unicode 属性"

需要在 /i 下进行不同匹配的用户定义属性处理程序必须更改为读取传递给它们的新布尔参数,如果区分大小写匹配生效,则该参数为非零值,否则为 0。请参见 "perlunicode 中的用户定义字符属性"

\p{} 意味着 Unicode 语义

在模式中指定 Unicode 属性表示该模式旨在根据 Unicode 规则进行匹配,就像 \N{NAME} 一样。

正则表达式在插值时保留其本地性

use locale 下编译的正则表达式现在在插值到在 use locale 之外编译的新正则表达式时保留此特性,反之亦然。

以前,一个正则表达式插值到另一个正则表达式会继承周围正则表达式的本地性,从而丢失其最初具有的任何状态。这被认为是一个错误修复,但可能会影响依赖于错误行为的代码。

正则表达式的字符串化已更改

默认的正则表达式修饰符现在使用 (?^...) 表示。依赖于旧字符串化的代码将失败。这样做是为了当添加新的修饰符时,此类代码不必每次都更改,因为字符串化将自动包含新的修饰符。

需要与旧式和新式正则表达式一起正常工作的代码可以通过使用以下方法来避免整个问题(对于 5.9.5 之后的 perl 版本;请参见 re

use re qw(regexp_pattern);
my ($pat, $mods) = regexp_pattern($re_ref);

如果实际的字符串化很重要或需要支持旧版本的 Perl,可以使用以下方法

# Accept both old and new-style stringification
my $modifiers = (qr/foobar/ =~ /\Q(?^/) ? "^" : "-xism";

然后使用 $modifiers 而不是 -xism

运行时正则表达式中的代码块继承了语义

正则表达式中的代码块((?{...})(??{...}))以前不会继承语义(严格、警告等),如果正则表达式是在运行时编译的,就像下面这两个例子一样

use re "eval";
$foo =~ $bar; # when $bar contains (?{...})
$foo =~ /$bar(?{ $finished = 1 })/;

此错误现已修复,但依赖于错误行为的代码可能需要修复以适应正确的行为。

存储区和包变量

本地化的绑定哈希和数组不再绑定

在以下情况下

    tie @a, ...;
    {
	    local @a;
	    # here, @a is a now a new, untied array
    }
    # here, @a refers again to the old, tied array

早期版本的 Perl 错误地绑定了新的本地数组。现在已修复此问题。但是,此修复可能会导致某些代码的行为发生变化。

存储区现在始终定义

defined %Foo:: 现在始终返回 true,即使该包中尚未定义任何符号。

这是从令牌器中删除特殊情况 kludge 的副作用,该 kludge 是为 5.10.0 添加的,以隐藏对哈希内部存储的更改的副作用。此修复极大地减少了哈希的内存开销。

自 5.6.0 起,对存储区调用 defined 已被弃用,自 5.6.0 起对词法变量发出警告,自 5.12.0 起对存储区和其他包变量发出警告。defined %hash 一直暴露了一个实现细节:通过删除哈希中的所有条目来清空哈希不会使 defined %hash 成为 false。因此,defined %hash 不是用于确定任意哈希是否为空的有效代码。相反,请使用空 %hash 在标量上下文中始终返回 false 的行为。

清除存储区

存储区列表赋值 %foo:: = () 以前会在清空存储区时将其临时设为匿名。因此,任何在其他地方引用的子例程都将变为匿名,在 caller 中显示为“(unknown)”。它们现在保留其包名称,以便如果仍然存在对其类型全局的引用,caller 将返回原始子例程名称,否则返回“foo::__ANON__” [perl #79208]。

解引用类型全局

如果您将类型全局分配给标量变量

$glob = *foo;

复制到 $glob 的全局将用一个特殊标志标记,该标志指示全局只是一个副本。这允许后续对 $glob 的赋值覆盖全局。但是,原始全局是不可变的。

一些 Perl 运算符没有区分这两种类型的 glob。这会导致边缘情况下的奇怪行为:untie $scalar 不会取消绑定标量,如果最后分配给它的值是一个 glob(因为它将其视为 untie *$scalar,这会取消绑定句柄)。分配给 glob 槽(例如 *$glob = \@some_array)只会将 \@some_array 分配给 $glob

为了解决这个问题,*{} 运算符(包括其 *foo*$foo 形式)已被修改,如果其操作数是 glob 副本,则会创建一个新的不可变 glob。这允许区分 glob 和标量的运算符被修改为仅将不可变 glob 视为 glob。(tietieduntie 为了兼容性而保留,但会发出警告。参见 "弃用"。)

这会导致将 glob 分配给 *{} 的返回值的代码发生不兼容的更改,当该运算符传递了一个 glob 副本时。例如,以下代码

$glob = *foo;
*$glob = *bar;

第二行上的 *$glob 返回一个新的不可变 glob。该新 glob 被设置为 *bar 的别名。然后它被丢弃。因此,第二次赋值没有效果。

有关更多详细信息,请参见 https://github.com/Perl/perl5/issues/10625

主包之外的魔法变量

在以前的 Perl 版本中,像 $!%SIG 等等的魔法变量会“泄漏”到其他包中。因此,%foo::SIG 可以用来访问信号,${"foo::!"}(在关闭严格模式的情况下)用来访问 C 的 errno 等等。

这是一个错误,或者是一个“无意”的功能,它会导致各种不良影响,例如在加载模块时信号处理程序被清除等等。

这个问题已经得到修复(或者该功能已被移除,取决于你的看法)。

local($_) 从 $_ 中删除所有魔法

标量变量上的 local() 会赋予它们一个新值,但会保留所有魔法。这对于默认标量变量 $_ 来说已被证明是有问题的,在 perlsub 中建议,任何分配给 $_ 的子程序都应该先对其进行本地化。如果 $_ 与只读变量别名,这将抛出异常,并且通常会导致各种意想不到的副作用。

因此,作为一般规则的例外,local($_) 不仅会为 $_ 赋值,还会删除其所有现有的魔法。

包名和变量名的解析

解析包名和包变量名的方式已更改:现在,多个相邻的冒号对,如 foo::::bar,都被视为包分隔符。

无论此更改如何,包分隔符的精确解析从未得到保证,并且可能会在将来的 Perl 版本中发生变化。

语法或 Perl 运算符的更改

given 返回值

given 块现在返回最后一个计算的表达式,如果块通过 break 退出,则返回空列表。因此,您现在可以编写

my $type = do {
 given ($num) {
  break     when undef;
  "integer" when /^[+-]?[0-9]+$/;
  "float"   when /^[+-]?[0-9]+(?:\.[0-9]+)?$/;
  "unknown";
 }
};

有关详细信息,请参阅 "perlsyn 中的返回值"

某些原型解析的更改

使用以下原型声明的函数现在可以正确地作为一元函数运行

*
\$ \% \@ \* \&
\[...]
;$ ;*
;\$ ;\% etc.
;\[...]

由于此错误修复 [perl #75904],使用 (*)(;$)(;*) 原型的函数的解析优先级高于以前。因此,在以下示例中

sub foo(;$);
foo $a < $b;

第二行现在被正确地解析为 foo($a) < $b,而不是 foo($a < $b)。当这些运算符之一在未加括号的参数中使用时,就会发生这种情况

< > <= >= lt gt le ge
== != <=> eq ne cmp ~~
&
| ^
&&
|| //
.. ...
?:
= += -= *= etc.
, =>

与数组切片进行智能匹配

以前,以下代码会导致成功匹配

my @a = qw(a y0 z);
my @b = qw(a x0 z);
@a[0 .. $#b] ~~ @b;

此奇怪的行为现已修复 [perl #77468]。

否定运算符对字符串的处理方式与以前不同

一元否定运算符 - 现在将看起来像数字的字符串视为数字 [perl #57706]。

负零

负零 (-0.0) 转换为字符串后,现在在所有平台上都变为 "0"。它过去在某些平台上变为 "-0",但在其他平台上变为 "0"。

如果您仍然需要确定零是否为负数,请使用 sprintf("%g", $zero) =~ /^-/ 或 CPAN 上的 Data::Float 模块。

:= 现在是语法错误

以前 my $pi := 4my $pi : = 4 完全等效,: 被视为属性列表的开始,在 = 之前结束。在 5.12.0 中,使用 := 表示 : = 已被弃用,现在是语法错误。这允许将来使用 := 作为新的标记。

除了核心测试之外,我们在 CPAN 上没有发现使用这种构造的 Perl 5 代码,因此我们认为此更改对现实世界中的代码库影响很小。

如果绝对有必要使用空属性列表(例如,由于代码生成器),只需在 = 之前添加一个空格来避免错误。

标识符解析的更改

Unicode "XIDStart" 集之外的字符不再允许作为标识符的开头。这意味着某些通常跟随字母字符的重音符号和标记可能不再是标识符的第一个字符。

线程和进程

目录句柄不会复制到线程

在没有 fchdir 函数的非 Windows 系统上,新创建的线程不再从其父线程继承目录句柄。此类程序通常会崩溃 [perl #75154]。

共享管道上的 close

为了避免死锁,close 函数不再等待子进程退出,如果底层文件描述符仍在其他线程中使用。在这种情况下,它将返回 true。

fork() 模拟不会等待已发出信号的子进程

在 Windows 上,父进程不会终止,直到所有派生的子进程都先终止。但是,kill("KILL", ...) 在伪进程上本质上是不稳定的,并且如果子进程在系统调用中被阻塞,则 kill("TERM", ...) 可能不会被传递。

为了避免死锁并提供一种安全机制来终止托管进程,Perl 现在不再等待已发送 SIGTERM 信号的子进程。父进程有责任等待这些子进程,如果必须允许子进程清理处理完成。但是,父进程也有责任通过确保子进程不会被阻塞在 I/O 上来避免死锁。

有关 Windows 上 fork() 模拟的更多信息,请参阅 perlfork

配置

Policy_sh.SH 中的命名修复可能会使 Policy.sh 无效

Policy_sh.SH 中的几个长期存在的拼写错误和命名混淆已得到修复,标准化了 config.sh 中使用的变量名称。

如果您碰巧依赖于其不正确的行为,这将改变 Policy.sh 的行为。

Perl 源代码在 Windows 上以文本模式读取

为了使用 ByteLoader 模块(不再是 Perl 核心的一部分),Perl 脚本在 Windows 上以前是以二进制模式读取的。这会造成对 DATA 文件句柄的各种操作出现问题,包括 seek()/tell(),甚至是在文件句柄被 system()、反引号、fork() 等调用刷新后简单地从 DATA 中读取。

Windows 的默认构建选项已更改为现在以文本模式读取 Windows 上的 Perl 源代码。 ByteLoader 将(希望)在 CPAN 上更新以自动处理这种情况 [perl #28106]。

弃用

另请参阅 "已弃用的 C API"

省略正则表达式和后续词之间的空格

省略正则表达式运算符或其修饰符与其后的词之间的空格已被弃用。例如,m/foo/sand $bar 目前仍然被解析为 m/foo/s and $bar,但现在会发出警告。

\cX

反斜杠-c 结构被设计为指定不可打印字符的一种方式,但对 c 后的字符没有限制(在 ASCII 平台上)。现在,如果该字符不是 ASCII 字符,则会发出弃用警告。此外,对于 "\c{"(与简单地说 ";" 相同)也会发出弃用警告。

"\b{""\B{"

在正则表达式中,紧跟在 "\b"(不在方括号字符类中)或 "\B{" 后的字面量 "{" 现在已被弃用,以便 Perl 本身将来可以使用它。

Perl 4 时代的 .pl 库

Perl 包含一些早于 Perl 5 的库文件。现在,大多数这些文件的捆绑已被弃用,这些文件现在可以在 CPAN 上获得。如果这些文件作为核心的一部分安装,则在运行时会发出警告。

这是一个强制性警告,不遵守 -X 或词法警告位。该警告的模型是 deprecate.pm 为核心中的已弃用 .pm 库提供的警告。它指向包含 .pl 库的特定 CPAN 发行版。当然,CPAN 版本不会生成警告。

列表赋值给 $[

将值赋予 $[ 已被弃用,并在 Perl 版本 5.12.0 中开始发出警告。此版本的 Perl (5.14) 现在在列表上下文中将值赋予 $[ 时也会发出警告。这修正了 5.12.0 中的疏漏。

使用 qw(...) 作为括号

从历史上看,解析器会误以为 qw(...) 字面量始终包含在括号中,因此您有时可以省略它们周围的括号。

for $x qw(a b c) { ... }

解析器不再以这种方式欺骗自己。将列表字面量用括号括起来,例如:

for $x (qw(a b c)) { ... }

之所以弃用此功能,是因为 for $i (1,2,3) { ... } 中的括号不是表达式语法的一部分。它们是语句语法的一部分,for 语句需要字面量括号。qw 表达式获得的合成括号仅用于作为表达式语法的一部分。

请注意,这不会改变类似以下情况的行为:

use POSIX qw(setlocale localeconv);
our @EXPORT = qw(foo bar baz);

在这些情况下,表达式周围从未需要括号。

\N{BELL}

这是因为 Unicode 使用该名称来表示不同的字符。有关更多解释,请参阅 "Unicode 版本 6.0 现在已支持(大部分)"

?PATTERN?

?PATTERN?(没有初始的 m)已被弃用,现在会产生警告。这是为了允许在新的运算符中将来使用 ?。一次匹配功能仍然可以使用 m?PATTERN?

在保存类型全局变量的标量上使用绑定函数

使用标量参数调用绑定函数(tietieduntie)会在标量恰好保存类型全局变量时作用于文件句柄。

这是一个长期存在的错误,将在 Perl 5.16 中移除,因为目前没有办法在标量包含类型全局变量时绑定标量本身,也没有办法解除绑定已分配类型全局变量的标量。

现在,每当在没有显式 `*` 的句柄上使用 tie 函数时,都会出现弃用警告。

用户定义的大小写映射

此功能由于其许多问题而被弃用,如 "perlunicode 中的用户定义大小写映射(仅供高级黑客使用)" 中所述。此功能将在 Perl 5.16 中移除。请改用 CPAN 模块 Unicode::Casing,它提供了改进的功能。

已弃用模块

以下模块将在未来版本中从核心发行版中移除,应从 CPAN 安装。CPAN 上需要此模块的发行版应将其添加到其先决条件中。这些模块的核心版本现在会发出弃用警告。

如果您发布了 Perl 的打包版本,无论是单独发布还是作为更大系统的一部分,那么您应该仔细考虑核心模块弃用的影响。您可能需要考虑将您的默认 Perl 构建与一个用于弃用模块的包一起发布,该包安装到 `vendor` 或 `site` Perl 库目录中。这将抑制弃用警告。

或者,您可能需要考虑修补 `lib/deprecate.pm` 以提供特定于您的打包系统或 Perl 发行版的弃用警告,与您的打包系统或发行版如何管理从单个包提供给定功能的版本到系统管理员需要知道安装多个包才能获得相同功能的版本的过渡阶段一致。

您可以通过从 CPAN 安装有问题的模块来消除这些弃用警告。要按角色而不是按名称安装其最新版本,只需安装 `Task::Deprecations::5_14`。

Devel::DProf

我们强烈建议您安装并使用 Devel::NYTProf 而不是 Devel::DProf,因为 Devel::NYTProf 提供了显着改进的性能分析和报告功能。

性能增强

"安全信号" 优化

信号调度已从运行循环移至控制操作。这应该会带来百分之几的速度提升,并且消除了在 5.8.0 中引入 "安全信号" 导致的几乎所有速度损失。信号应该仍然在与以前相同的语句中调度。如果这种情况没有发生,或者如果您发现可以创建不可中断的循环,那么这是一个错误,鼓励报告如何重现此类问题。

没有参数的 shift() 和 pop() 调用的优化

对于没有参数(隐式 `@_`)的 shift() 和 pop() 调用,使用了两个更少的 OP。此更改使 shift() 在非线程化的 perl 上比 `shift @_` 快 5%,在线程化的 perl 上快 25%。

正则表达式引擎字符串比较工作的优化

用于字符串不区分大小写比较的 foldEQ_utf8 API 函数(正则表达式引擎大量使用)进行了实质性的重构和优化,并且作为免费赠品,其文档也得到了很大改进。

正则表达式编译速度提升

当需要将正则表达式升级到 utf8 时,编译正则表达式速度更快,但在编译开始时并不知道这一点。

字符串追加速度提高了 100 倍

在进行大量字符串追加时,构建为使用系统 malloc 的 Perl 可能会以低效的方式最终分配比需要的更多的内存。

sv_grow 是用于在追加到字符串时在必要时分配更多内存的函数,它已被教会将它请求的内存向上舍入到某个几何级数,使其在某些平台和配置上速度更快。在 Win32 上,它现在快了大约 100 倍。

在 ithreads 下消除 PL_* 访问器函数

MULTIPLICITY 首次开发时,解释器状态被移入解释器结构体,线程和解释器局部 PL_* 变量被定义为宏,这些宏调用访问器函数(返回值的地址)在 Perl 核心之外。目的是允许解释器结构体内的成员更改大小而不破坏二进制兼容性,以便可以将错误修复合并到需要这种大小更改的维护分支。这种机制是多余的,并且会惩罚行为良好的代码。它已被删除。

释放弱引用

当存在许多对某个对象的弱引用时,在某些情况下,释放该对象可能需要 O(N*N) 时间才能释放,其中 N 是引用的数量。发生这种情况的情况已减少 [perl #75254]

词法数组和哈希赋值

早期的优化旨在加速 my @array = ...my %hash = ... 赋值,但导致了一个 bug,并在 Perl 5.12.0 中被禁用。

现在我们找到了另一种加速这些赋值的方法 [perl #82110]。

@_ 使用更少的内存

以前,@_ 在编译时为每个子程序分配了足够容纳四个条目的空间。现在,这种分配是在子程序被调用时按需进行的 [perl #72416]。

SV 和 HV 结构的大小优化

xhv_fill 已从 struct xpvhv 中移除,为每个哈希节省了 1 个 IV,并且在某些系统上会使 struct xpvhv 变得缓存对齐。为了避免这种内存节省导致其他地方的性能下降,HvFILL 的布尔值使用现在改为调用 HvTOTALKEYS(等效),因此,虽然实际需要时填充数据现在是按需计算的,但需要进行此操作的情况应该很少见。

SV 主体中结构元素的顺序已更改。实际上,NV 槽已与 STASH 和 MAGIC 交换位置。由于对 SV 成员的所有访问都是通过宏进行的,因此这应该是完全透明的。此更改允许上面记录的 PVHV 的空间节省,并且可能会减少某些架构上 PVIV 所需的内存分配。

XPVXPVIVXPVNV 现在只分配它们实际使用的 SV 主体部分,节省了一些空间。

包含正则表达式的标量现在只分配它们实际使用的 SV 主体部分,节省了一些空间。

Exporter 的内存消耗改进

@EXPORT_FAIL AV 只有在需要时才会创建,因此支持它的 typeglob 也不会创建。这为每个使用 Exporter 但不使用此功能的包节省了大约 200 字节。

弱引用的内存节省

对于弱引用,每个被引用者只有一个弱引用的常见情况已进行了优化,以减少所需的存储空间。在这种情况下,它节省了相当于每个被引用者一个小型 Perl 数组的空间。

%+%- 使用更少的内存

Tie::Hash::NamedCapture 模块的大部分内容以前位于 Perl 核心代码中。现在它已移至 XS 模块,以减少不使用 %+%- 的程序的开销。

对线程的多个小改进

线程的内部结构现在减少了 API 调用和分配,从而导致对象代码明显更小。此外,许多线程上下文检查已被推迟,因此它们仅在需要时才执行(尽管这仅适用于非调试版本)。

相邻的 nextstate 操作码对现在被优化掉了

以前,在以下代码中

use constant DEBUG => 0;

sub GAK {
    warn if DEBUG;
    print "stuff\n";
}

warn if DEBUG 的操作将折叠为 null 操作(ex-const),但 nextstate 操作将保留,导致 nextstatenextstate 等的运行时操作调度。

执行一系列nextstate操作与仅执行最后一个nextstate操作的效果相同,因此 peephole 优化器现在会消除一对nextstate操作中的第一个,除非第一个操作带有标签,因为标签不能被优化器消除,并且标签的使用情况在编译时无法确定。

模块和语义

新增模块和语义

更新的模块和pragma

已删除的模块和 pragma

如 Perl 5.12.0 发行说明中所述,以下模块已从核心发行版中删除,如果需要,应从 CPAN 安装。

删除 Shell 的操作已推迟到 5.14 之后,因为与 5.12.0 一起提供的 Shell 实现没有正确发出有关其将从核心删除的警告。

文档

新文档

perlgpl

perlgpl 已更新,包含 GPL 版本 1,该版本包含在 Perl (5.12.1) 附带的 README 中。

Perl 5.12.x 版本差异文件

Perl 5.12.1 到 5.12.3 的版本差异文件已从维护分支添加:perl5121deltaperl5122deltaperl5123delta

perlpodstyle

POD 文档的新样式指南,主要从 pod2man(1) 手册页的 NOTES 部分拆分而来。

perlsourceperlinterpperlhacktutperlhacktips

参见下面的 "perlhack 和 perlrepository 改进"

现有文档的更改

perlmodlib 现已完成

Perl 5.12.0 附带的 perlmodlib 手册页缺少几个模块,因为生成列表的脚本存在错误。此错误已修复 [perl #74332] (5.12.1)。

替换 perlebcdic 中不正确的 tr/// 表

perlebcdic 包含一个有用的表格,用于在 tr/// 中转换 EBCDIC 和 Latin1/ASCII。虽然该表是其描述的表的反向,但使用该表的代码在给定的特定示例中可以正常工作。

该表已更正,示例代码也已更改以对应。

该表也已从八进制更改为十六进制,并且 pod 中的示例已更改为打印前导零,以使所有值具有相同的长度。

用户定义大小写的技巧

perlunicode 现在包含对如何覆盖、修改和以其他方式调整 Perl 处理 Unicode 数据的大写、小写和其他大小写转换的方式的解释,以及如何提供作用域更改以更改自己的代码的行为,而不会踩到其他人的代码。

INSTALL 明确说明 Perl 需要 C89 编译器

这本来就是事实,但现在已正式记录在案 (5.12.2)。

\xHH\oOOO 转义的解释

perlop 已更新,包含对这两种字符转义的更详细解释。

-0NNN 开关

perlrun 中,-0NNN 开关对于 -0400 或更高版本的行为已澄清 (5.12.2)。

维护策略

perlpolicy 现在包含有关哪些补丁适用于维护分支的策略 (5.12.1)。

弃用策略

perlpolicy 现在包含了关于兼容性和弃用的策略,以及“弃用”等术语的定义(5.12.2)。

perldiag 中的新描述

以下现有诊断现在已记录

perlbook

perlbook 已扩展到涵盖更多流行书籍。

SvTRUE

perlapiSvTRUE 宏的文档在说明 get-magic 未被处理方面是错误的。它已被更正。

op 操作函数

几个处理 optree 的 API 函数已新增文档。

perlvar 改版

perlvar 重新排列了变量,并按主题进行分组。每个在 Perl 5.000 之后引入的变量都记录了它首次可用的版本。 perlvar 还为弃用的变量新增了一个部分,以记录它们何时被移除。

标量上下文中的数组和哈希切片

这些现在已在 perldata 中记录。

use locale 和格式

perlformperllocale 已更正,以说明 use locale 会影响格式。

overload

overload 的文档实际上已经过重写。它现在更加直接和清晰。

perlhack 和 perlrepository 改版

perlhack 文档现在更短,重点关注 Perl 5 的开发流程和向 Perl 提交补丁。技术内容已移至几个新文档,perlsourceperlinterpperlhacktutperlhacktips。这些技术内容仅进行了轻微的编辑。

perlrepository 文档已重命名为 perlgit。这个新文档只是关于使用 git 与 Perl 源代码的说明。perlrepository 中以前包含的任何其他内容都已移至 perlhack

Time::Piece 示例

perlfaq4 中的示例已更新以显示 Time::Piece 的用法。

诊断信息

诊断输出(包括警告和致命错误消息)已进行以下添加或更改。有关诊断消息的完整列表,请参阅 perldiag

新的诊断信息

新的错误

调用闭包原型

如果传递给属性处理程序的子程序引用被调用,并且该子程序是闭包,则会发生此错误 [perl #68560]。

不安全的用户定义属性 %s

当尝试编译包含对用户定义字符属性函数调用的正则表达式时,Perl 检测到污染数据,这意味着 \p{IsFoo}\p{InFoo}。请参阅 "perlunicode 中的用户定义字符属性"perlsec

panic: gp_free 无法释放 glob 指针 - 某些东西正在重复创建条目

如果在要释放的 typeglob 中的对象上调用的析构函数创建了一个新的 typeglob 条目,其中包含一个具有析构函数的对象,该析构函数创建了一个新的包含对象的条目,依此类推,则会触发此新错误。

解析代码内部错误 (%s)

当扩展提供的解析代码以可检测的方式违反解析器的 API 时,会产生此新的致命错误。

refcnt: fd %d%s

此新错误仅在管道即将关闭时内部一致性检查失败时才会发生。

正则表达式修饰符 "/%c" 不能出现两次

正则表达式模式重复了一个互斥的修饰符。

正则表达式修饰符 "/%c" 和 "/%c" 是互斥的

正则表达式模式具有多个互斥的修饰符。

使用 !~ 与 %s 没有意义

!~s///ry///r 一起使用时,会发生此错误。

新的警告

"\b{" 已弃用;请使用 "\b\{" 代替
"\B{" 已弃用;请使用 "\B\{" 代替

\b\B 后面直接使用未转义的 "{" 现在已弃用,以便在将来的版本中为 Perl 本身保留其使用。

操作 "%s" 返回其参数,用于...

对 Unicode 代理或非 Unicode 字符执行需要 Unicode 语义的操作(例如大小写折叠)现在会触发此警告。

使用 qw(...) 作为括号已弃用

有关详细信息,请参见上面的 "使用 qw(...) 作为括号"

对现有诊断的更改

实用程序更改

perlbug(1)

perl5db.pl

ptargrep

配置和编译

另请参见上面的 "Policy_sh.SH 中的命名修复可能会使 Policy.sh 无效"

平台支持

新平台

AIX

Perl 现在可以在 AIX 4.2 上构建(5.12.1)。

已停产的平台

Apollo DomainOS

Perl 发行版中已删除对该平台的最后支持。它在 5.12.0 版本中正式停止支持。在此之前,它已经多年无法正常工作。

MacOS Classic

Perl 发行版中已删除对该平台的最后支持。它在早期版本中正式停止支持。

平台特定说明

AIX

ARM

Cygwin

FreeBSD 7

HP-UX

IRIX

Mac OS X

MirBSD

NetBSD

OpenBSD

OpenVOS

Solaris

VMS

Windows

另请参见上面的 "fork() 模拟不会等待信号子进程""Perl 源代码在 Windows 上以文本模式读取"

内部更改

新 API

添加了 CLONE_PARAMS 结构以简化正确的线程创建

创建线程的模块现在应该通过调用新函数 Perl_clone_params_new() 来创建 CLONE_PARAMS 结构,并使用 Perl_clone_params_del() 释放它们。这将确保与 CLONE_PARAMS 结构布局内部的任何未来更改兼容,并确保它被正确分配和初始化。

新的解析函数

添加了几个用于解析 Perl 语句和表达式的函数。这些函数旨在由 Perl 解析期间调用的 XS 代码以递归下降的方式使用,以允许模块扩展标准 Perl 语法。

Hints 哈希 API

添加了一个新的 C API 用于在运行时检查 hinthash %^H。有关详细信息,请参阅 perlapi 中的 cop_hints_2hvcop_hints_fetchpvncop_hints_fetchpvscop_hints_fetchsvhv_copy_hints_hv

添加了一个新的实验性 API 用于访问 Perl 用于 %^H 的内部结构。请参阅 perlapi 中以 cophh_ 开头的函数。

C 接口到 caller()

已添加 caller_cx 函数作为 XSUB 编写者的 caller() 等效项。有关详细信息,请参阅 perlapi

自定义每个子例程的检查钩子

扩展模块中的 XS 代码现在可以注释一个子例程(无论是在 XS 中实现还是在 Perl 中实现),以便在编译时(具体来说,作为操作检查的一部分)调用指定的 XS 代码来更改该子例程的操作树。编译时检查函数(由扩展模块提供)可以实现无法用原型表达的参数处理,生成自定义的编译时警告,对纯函数执行常量折叠,内联由足够简单的操作组成的子例程,用自定义操作替换整个调用,等等。以前可以通过挂钩 entersub 操作检查器来实现所有这些,但新机制使将钩子绑定到特定子例程变得容易。请参阅 "perlapi 中的 cv_set_call_checker"

为了帮助编写自定义检查钩子,标准entersub操作检查中的几个子任务已被分离出来并在 API 中公开。

改进对自定义 OP 的支持

自定义操作现在可以使用新的 custom_op_register C 函数和 XOP 结构进行注册。这将使将来更容易添加自定义操作的新属性。已经添加了两个新属性,xop_classxop_peep

xop_class 是 OA_*OP 常量之一。它允许 B 和其他内省机制与不是 BASEOP 的自定义操作一起使用。xop_peep 是一个指向函数的指针,该函数将从 Perl_rpeep 为此类型的操作调用。

有关更多详细信息,请参阅 "perlguts 中的自定义操作""perlapi 中的自定义操作"

旧的 PL_custom_op_names/PL_custom_op_descs 接口仍然受支持,但已不再推荐使用。

作用域钩子

现在,XS 代码可以使用新的 Perl_blockhook_register 函数在编译时挂接到 Perl 的词法作用域机制。请参阅 "perlguts 中的编译时作用域钩子"

窥视孔优化器的递归部分现在可以挂钩

除了 PL_peepp(用于挂接到顶层窥视孔优化器)之外,现在还提供了一个 PL_rpeepp 用于挂接到递归到 optree 侧链的优化器。

现有函数的新非魔法变体

以下函数/宏已添加到 API 中。*_nomg 宏等效于它们非 _nomg 变体,只是它们忽略 get-magic。那些以 _flags 结尾的允许您指定是否处理 get-magic。

sv_2bool_flags
SvTRUE_nomg
sv_2nv_flags
SvNV_nomg
sv_cmp_flags
sv_cmp_locale_flags
sv_eq_flags
sv_collxfrm_flags

在其中一些情况下,非 _flags 函数已被替换为围绕新函数的包装器。

现有函数的 pv/pvs/sv 版本

许多以 pvn 结尾的函数现在都有等效的 pv/pvs/sv 版本。

列表操作构建函数

列表操作构建函数已添加到 API 中。请参阅 op_append_elemop_append_listop_prepend_elemperlapi 中。

LINKLIST 宏(操作构建的一部分,用于构建执行顺序操作链)已添加到 API 中。

本地化函数

API 中添加了 save_freeopsave_opsave_pushi32ptrsave_pushptrptr 函数。

Stash 名称

Stash 现在除了通常的名称外,还可以拥有一个有效名称列表。第一个有效名称可以通过 HvENAME 宏访问,现在推荐在 MRO 线性化中使用此名称(如果不存在 HvENAME,则 HvNAME 为备用名称)。

这些名称通过 hv_ename_addhv_ename_delete 添加和删除。这两个函数属于 API 的一部分。

用于查找和删除魔术的新函数

API 中添加了 mg_findext()sv_unmagicext() 函数。它们允许扩展作者根据魔术类型和魔术虚拟表查找和删除附加到标量的魔术,类似于 sv_magicext() 如何将特定类型和给定虚拟表的魔术附加到标量。这消除了扩展需要遍历 SVMAGIC 指针列表以查找属于它们的魔术的必要性。

find_rundefsv

此函数返回表示 $_ 的 SV,无论它是词法还是动态的。

Perl_croak_no_modify

Perl_croak_no_modify()Perl_croak("%s", PL_no_modify) 的简写。

PERL_STATIC_INLINE 定义

PERL_STATIC_INLINE 定义已添加,以提供用于静态内联函数的最佳猜测咒语,如果 C 编译器支持 C99 样式的静态内联。如果它不支持,它将提供一个普通的 static

HAS_STATIC_INLINE 可用于检查编译器是否实际支持内联函数。

pv_escape 用于十六进制转义的新选项

pv_escape 中添加了一个新选项 PERL_PV_ESCAPE_NONASCII,用于以十六进制形式转储所有高于 ASCII 的字符。之前,可以将所有字符作为十六进制或 Latin1 非 ASCII 作为八进制获取。

lex_start

lex_start 已添加到 API 中,但被认为是实验性的。

op_scope() 和 op_lvalue()

op_scope() 和 op_lvalue() 函数已添加到 API 中,但被认为是实验性的。

C API 更改

PERL_POLLUTE 已被移除

定义 PERL_POLLUTE 以公开旧的 5.005 符号以实现向后兼容性的选项已被移除。一直不鼓励使用它,并且 MakeMaker 包含一个更具体的逃生舱口。

perl Makefile.PL POLLUTE=1

这可用于尚未升级到 5.6 命名约定的模块(现在应该完全过时了)。

加载 XS 模块时检查 API 兼容性

当 Perl 的 API 以不兼容的方式发生更改时(通常发生在主要版本之间),为先前版本的 Perl 编译的 XS 模块将不再起作用。它们需要针对新的 Perl 重新编译。

XS_APIVERSION_BOOTCHECK 宏已添加以确保模块被重新编译,并防止用户意外地将为旧 Perl 编译的模块加载到较新的 Perl 中。该宏在加载每个新编译的扩展时被调用,它将运行时 Perl 的 API 版本与模块编译的版本进行比较,如果它们不匹配,则会引发异常。

Perl_fetch_cop_label

C API 函数 Perl_fetch_cop_label 的第一个参数已从 struct refcounted_he * 更改为 COP *,以隔离用户免受实现细节的影响。

此 API 函数被标记为“可能会更改”,并且可能不在核心之外使用。(既没有解压缩的 CPAN 也没有 Google 的代码搜索找到了对它的任何其他引用。)

GvCV() 和 GvGP() 不再是左值

现在提供新的 GvCV_set() 和 GvGP_set() 宏来替换对这两个宏的赋值。

这允许将来的提交消除 GV 和 CV 之间的某些反向引用魔法,这将需要完全控制对 gp_cv 插槽的赋值。

CvGV() 不再是左值

在某些情况下,CV 的 CvGV() 字段现在是引用计数的。为了确保一致的行为,对它的直接赋值,例如 CvGV(cv) = gv 现在是编译时错误。已引入一个新的宏 CvGV_set(cv,gv) 来安全地运行此操作。请注意,无论此新宏如何(以及尽管它列在这个部分中),修改此字段都不属于公共 API 的一部分。

CvSTASH() 不再是左值

CvSTASH() 宏现在只能用作右值。已添加 CvSTASH_set() 来替换对 CvSTASH() 的赋值。这是为了确保正确处理反向引用。这些宏不是 API 的一部分。

newFOROPnewWHILEOP 的调用约定

解析器处理标签的方式已清理并重构。因此,newFOROP() 构造函数不再接受一个参数来指定要放在状态操作中的标签。

newWHILEOP() 和 newFOROP() 函数不再接受行号作为参数。

传递给 uvuni_to_utf8_flagsutf8n_to_uvuni 的标志

传递给 uvuni_to_utf8_flags() 和 utf8n_to_uvuni() 的一些标志参数已更改。这是由于 Perl 现在允许内部存储和操作在某些情况下存在问题的代码点。因此,这些函数的默认操作已得到补充,以允许这些代码点。新标志在 perlapi 中有记录。需要拒绝有问题的代码点的代码需要更改为使用新标志。一些标志名称保留用于向后源代码兼容性,尽管它们什么也不做,因为它们现在是默认值。但是,标志 UNICODE_ALLOW_FDD0UNICODE_ALLOW_FFFFUNICODE_ILLEGALUNICODE_IS_ILLEGAL 已被删除,因为它们源于一个关于如何处理 Unicode 非字符代码点的根本错误模型,现在在 "perlunicode 中的非字符代码点" 中进行了描述。另请参阅 "选定的错误修复" 下的 Unicode 部分。

已弃用的 C API

Perl_ptr_table_clear

Perl_ptr_table_clear 不再是 Perl 公共 API 的一部分。现在调用它会生成弃用警告,并且将在未来的版本中删除。

sv_compile_2op

sv_compile_2op() API 函数现在已弃用。搜索表明 CPAN 上没有任何东西在使用它,因此这应该不会有任何影响。

它试图提供一个 API 来将代码编译成 optree,但未能正确绑定到封闭范围内的词法变量。在它的参数和返回值的约束下,无法解决这个问题。

find_rundefsvoffset

find_rundefsvoffset 函数已弃用。其设计似乎不足以可靠地获取运行时的词法 $_

请使用新的 find_rundefsv 函数或 UNDERBAR 宏。它们直接返回表示 $_ 的正确 SV,无论它是词法还是动态的。

CALL_FPTRCPERLscope

这些是使用 C++ 对象的旧 MULTIPLICITY 实现的遗留物,已在 Perl 5.8 中删除。如今,这些宏什么也不做,因此不再应该使用它们。

为了兼容性,它们仍然为外部 XS 代码定义。现在,只有定义了 PERL_CORE 的扩展需要更新。

其他内部更改

堆栈展开

die 的最后阶段展开 C 堆栈的协议已更改了它识别目标堆栈帧的方式。现在它使用一个单独的变量 PL_restartjmpenv,而以前它依赖于已名义上被丢弃的 eval 上下文帧中的 blk_eval.cur_top_env 指针。此更改意味着在 Perl 级别的展开的各个阶段运行的代码不再需要注意避免破坏幽灵帧。

作用域堆栈条目

作用域堆栈上的条目格式已更改,导致内存使用量减少了约 10%。特别是,作用域堆栈用于记录每个活动词法变量的内存已减半。

指针表的内存分配

指针表的内存分配已更改。以前,Perl_ptr_table_store 从与 SV 主体和 HE 相同的竞技场系统分配内存,释放的内存将一直绑定到这些竞技场,直到解释器退出。现在它从特定指针表的私有竞技场分配内存,并且当调用 Perl_ptr_table_free 时,该内存将返回到系统。此外,分配和释放都更少占用 CPU。

UNDERBAR

UNDERBAR 宏现在调用 find_rundefsvdUNDERBAR 现在是一个空操作,但仍应使用它来确保过去和将来的兼容性。

字符串比较例程已重命名

ibcmp_* 函数已重命名,现在称为 foldEQfoldEQ_localefoldEQ_utf8。旧名称仍然可用作宏。

chopchomp 实现合并

chopchomp 以及 schopschomp 的操作码主体已合并。实现函数 Perl_do_chop() 和 Perl_do_chomp() 从未成为公共 API 的一部分,现已合并并移至 pp.c 中的静态函数。这会稍微缩小 Perl 二进制文件,并且不应影响核心之外的任何代码(除非它依赖于 chomp 传递值列表时的副作用顺序)。

选定的错误修复

I/O

正则表达式错误修复

语法/解析错误

Stashes、Globs 和方法查找

Perl 5.10.0 引入了一种新的内部机制来缓存 MRO(方法解析顺序,或父类列表;也称为 "isa" 缓存),以使方法查找更快(因此 @ISA 数组不必重复搜索)。不幸的是,这带来了很多错误。现在几乎所有这些错误都已修复,以及一些在 5.10.0 之前存在的与 MRO 相关的错误。

此外,还修复了与类型全局变量和存储空间相关的各种其他错误。

Unicode

绑定、重载和其他魔法

调试器

线程

作用域和子程序

信号

其他内存泄漏

内存损坏和崩溃

各种 Perl 运算符的修复

与 C API 相关的错误

已知问题

这是一个关于重大未解决问题的列表,这些问题是早期版本的 Perl 的回归,或者会影响广泛使用的 CPAN 模块。

勘误

keys()、values() 和 each() 在数组上工作

您现在可以在数组上使用 keys()、values() 和 each() 内置函数;以前您只能在哈希上使用它们。有关详细信息,请参阅 perlfunc。这实际上是 perl 5.12.0 中引入的更改,但它在该版本的 perl5120delta 中被遗漏了。

split() 和 @_

split() 在标量或空上下文调用时不再修改 @_。在空上下文中,它现在会产生“split 的无用使用”警告。这也是 perl 5.12.0 中的更改,但它错过了 perldelta。

讣告

Randy Kobes,http://kobesearch.cpan.org/ 的创建者,以及多个核心 Perl 工具链模块的贡献者/维护者,于 2010 年 9 月 18 日因与肺癌作斗争后去世。社区因他的参与而更加丰富。他将被怀念。

致谢

Perl 5.14.0 代表了自 Perl 5.12.0 以来一年的开发,包含了来自 150 位作者和提交者的近 3,000 个文件中的近 550,000 行更改。

得益于充满活力的用户和开发者社区,Perl 继续在第三个十年蓬勃发展。以下人员已知为 Perl 5.14.0 的改进做出了贡献。

Aaron Crane, Abhijit Menon-Sen, Abigail, Ævar Arnfjörð Bjarmason, Alastair Douglas, Alexander Alekseev, Alexander Hartmaier, Alexandr Ciornii, Alex Davies, Alex Vandiver, Ali Polatel, Allen Smith, Andreas König, Andrew Rodland, Andy Armstrong, Andy Dougherty, Aristotle Pagaltzis, Arkturuz, Arvan, A. Sinan Unur, Ben Morrow, Bo Lindbergh, Boris Ratner, Brad Gilbert, Bram, brian d foy, Brian Phillips, Casey West, Charles Bailey, Chas. Owens, Chip Salzenberg, Chris 'BinGOs' Williams, chromatic, Craig A. Berry, Curtis Jewell, Dagfinn Ilmari Mannsåker, Dan Dascalescu, Dave Rolsky, David Caldwell, David Cantrell, David Golden, David Leadbeater, David Mitchell, David Wheeler, Eric Brine, Father Chrysostomos, Fingle Nark, Florian Ragwitz, Frank Wiegand, Franz Fasching, Gene Sullivan, George Greer, Gerard Goossen, Gisle Aas, Goro Fuji, Grant McLean, gregor herrmann, H.Merijn Brand, Hongwen Qiu, Hugo van der Sanden, Ian Goodacre, James E Keenan, James Mastros, Jan Dubois, Jay Hannah, Jerry D. Hedden, Jesse Vincent, Jim Cromby, Jirka Hruška, John Peacock, Joshua ben Jore, Joshua Pritikin, Karl Williamson, Kevin Ryde, kmx, Lars Dɪᴇᴄᴋᴏᴡ 迪拉斯, Larwan Berke, Leon Brocard, Leon Timmermans, Lubomir Rintel, Lukas Mai, Maik Hentsche, Marty Pauley, Marvin Humphrey, Matt Johnson, Matt S Trout, Max Maischein, Michael Breen, Michael Fig, Michael G Schwern, Michael Parker, Michael Stevens, Michael Witten, Mike Kelly, Moritz Lenz, Nicholas Clark, Nick Cleaton, Nick Johnston, Nicolas Kaiser, Niko Tyni, Noirin Shirley, Nuno Carvalho, Paul Evans, Paul Green, Paul Johnson, Paul Marquess, Peter J. Holzer, Peter John Acklam, Peter Martini, Philippe Bruhat (BooK), Piotr Fusik, Rafael Garcia-Suarez, Rainer Tammer, Reini Urban, Renee Baecker, Ricardo Signes, Richard Möhn, Richard Soderberg, Rob Hoelz, Robin Barker, Ruslan Zakirov, Salvador Fandiño, Salvador Ortiz Garcia, Shlomi Fish, Sinan Unur, Sisyphus, Slaven Rezic, Steffen Müller, Steve Hay, Steven Schubiger, Steve Peters, Sullivan Beck, Tatsuhiko Miyagawa, Tim Bunce, Todd Rinaldo, Tom Christiansen, Tom Hukins, Tony Cook, Tye McQueen, Vadim Konovalov, Vernon Lyon, Vincent Pit, Walt Mankowski, Wolfram Humann, Yves Orton, Zefram, 和 Zsbán Ambrus。

这非常不完整,因为它是由版本控制历史自动生成的。特别是,它不包括报告了以前版本中问题的贡献者(非常感谢)的姓名,这些问题帮助使 Perl 5.14.0 变得更好。有关所有 Perl 历史贡献者的更完整列表,请参阅 Perl 5.14.0 发行版中的 AUTHORS 文件。

本版本中包含的许多更改源自 Perl 核心包含的 CPAN 模块。我们感谢整个 CPAN 社区帮助 Perl 蓬勃发展。

报告错误

如果您发现您认为是错误,您可以查看最近发布到 comp.lang.perl.misc 新闻组的文章和 Perl 错误数据库 http://rt.perl.org/perlbug/ 。您也可以在 Perl 主页 https://www.perl5.cn/ 找到相关信息。

如果您认为您遇到了未报告的错误,请运行随您的发行版提供的 perlbug 程序。请务必将您的错误缩减为一个微小但足够的测试用例。您的错误报告以及 perl -V 的输出将被发送到 [email protected],由 Perl 移植团队进行分析。

如果您要报告的错误存在安全隐患,不适合发送到公开存档的邮件列表,请将其发送到 [email protected]。这指向一个封闭的订阅未存档邮件列表,其中包含所有核心提交者,他们能够帮助评估问题的影響,找出解决方案,并帮助协调在所有支持 Perl 的平台上发布补丁以减轻或解决问题。请仅将此地址用于 Perl 核心中的安全问题,不要用于独立分发在 CPAN 上的模块。

另请参阅

有关如何查看更改的详尽细节,请参阅 Changes 文件。

有关如何构建 Perl,请参阅 INSTALL 文件。

有关一般信息,请参阅 README 文件。

有关版权信息,请参阅 ArtisticCopying 文件。