在Perl中,CHECK、UNITCHECK和INIT块有什么用处?

在Perl中,CHECK、UNITCHECK和INIT块有什么用处?,perl,compilation,Perl,Compilation,我知道他们都在做什么,但我从未发现自己处于需要他们中任何一个的境地。我多次使用BEGIN块,偶尔使用ENDs块开始在代码运行前需要调整环境时特别有用,我在某些调试情况下使用了结束来捕获重要的状态信息,以跟踪难以跟踪的致命错误 您是否使用过CHECK、UNITCHECK或INIT?如果是,原因是什么?由于某种原因,BEGIN块是否不够 块的文档在上面。检查块的一个有趣用法是Simon Cozens(O'Reilly)在第1章“稍后使用检查做事情”一节中的“高级Perl编程”。他展示了如何实现“fi

我知道他们都在做什么,但我从未发现自己处于需要他们中任何一个的境地。我多次使用
BEGIN
块,偶尔使用
END
s块<代码>开始在代码运行前需要调整环境时特别有用,我在某些调试情况下使用了
结束
来捕获重要的状态信息,以跟踪难以跟踪的致命错误

您是否使用过
CHECK
UNITCHECK
INIT
?如果是,原因是什么?由于某种原因,
BEGIN
块是否不够


块的文档在上面。

检查块的一个有趣用法是Simon Cozens(O'Reilly)在第1章“稍后使用检查做事情”一节中的“高级Perl编程”。他展示了如何实现“final”类java属性


此外,Devel::Sub::Trace使用INIT块来接收跟踪(此信息来自用于处理这些命名块的模块Devel::Hook的POD)

我有一个包
导入
函数,该函数将执行一些繁重的处理,然后进行
eval
调用。如何调试这样的东西?当您
使用该模块时,导入函数就会运行,这发生在编译时(就像它在BEGIN块中一样)。出于某种原因(我认为这是因为我需要用herdoc符号将参数传递给
import
,但可能是其他原因),说
requiremodule不够好;模块->导入(@args)

因此,我的解决方法是在
import
中为
eval
构建字符串,并将其保存为另一个变量。
然后我在
INIT
块中运行
eval
。运行调试器时,第一个执行点位于
INIT
块的开头,我可以使用调试器逐步执行
eval
语句

Well
BEGIN
块在编译时运行,如您所知。所以我把它保存在需要运行的代码中,以便导入模块

我编写了一个脚本包装器,来完成在几百个脚本中出现的样板代码中所做的一切

  • 为了使模块读数
    use
    -d,我必须做一些事情。我在
    BEGIN
    块和
    import
    sub中运行的
  • 但也有所有的样板文件初始化脚本将使用的服务。因此,我在
    INIT
    块中运行了这些操作
  • 并在
    END
    块中运行必要的清理和退出代码
我认为,如果您使用XS引擎编写模块,检查是有意义的,但我只使用过几次。有一次,我认为这是为了检查中间Perl中的建议。我一时记不起其他原因了


但是当我觉得代码更多地是脚本的一部分而不是设置模块时,我会使用
INIT
块。本质上,我只在编译时执行必要的操作

perlmod解释了这些特殊块,但实际上通常只使用
BEGIN
END
。 它们只是CV、LIFO或FIFO的数组。 当代码运行时,这些块允许独立于源文件中的位置进行单独计时。因此,您可以将代码段放在一起,但它们在不同的时间执行(
阶段

最初添加的检查是为了在模块初始化之后(使用包)和主程序之前以固定顺序运行编译器套件O
-MO=C..
),以便能够在那里存储执行上下文。这将编译时(之前)和运行时(之后)分开。
perl-c
检查后停止

由于我是编译器的维护者,所以我广泛使用CHECK和-MO=命令。我的模块
compile()
方法由检查块中的O调用。使用Od(调试O),我调用
compile
方法,但不在CHECK中,而是稍后在INIT中调用,因此调试器会介入其中。调试器不会按照默认值进入检查块,您必须使用
$DB::single=1
或使用Od强制执行

UNITCHECK后来被添加到细粒度模块编译和加载中,尤其是
.pmc
文件中

到目前为止我还没用过。它也可能发生在运行时,所以我可能会使用它来检查运行时加载的模块的类型

然后添加了INIT,以允许单独的类初始化


我很少使用它,但它很方便。

现在我记得为什么我不想使用
require模块;模块->导入(@stuff)
。这是因为我已经有了一套测试脚本,我希望能够调试,并且我不想在每个文件中编辑
use Module
语句。调试编译时代码时,不需要经历这些扭曲。只要将$DB::single=1放在源代码中的任意位置,调试器就会在该位置停止,无论程序处于哪个处理阶段。(参见)此外,我从未尝试过,但这些可能被合理地用于一些有趣的模拟方法-如果有人有想法,请随意扩展此可能性作为单独的答案。Axeman-对于初始化,你能澄清一下你的用法吗?INIT block提供了一些特殊的东西,仅仅把INIT代码放在常规程序的开头是无法实现的?只是为了可视化/易于维护吗?@DVK:我在模块中使用了INIT块来执行类初始化;用户不应该知道这类事情。不幸的是,PAR::Packer在调度块(特别是INIT和CHECK)方面存在问题,因此这不适用于可能以这种方式分发的模块。我通常最后会撕掉INIT b