perl - 使用未初始化的变量是未定义的行为吗?
问题描述
我不知道“未定义的行为”在 Perl 中是否意味着什么,但我想知道在 Perl 中使用未初始化的变量是否会引发不需要的行为。
让我们考虑以下脚本:
use strict;
use warnings FATAL => 'all';
use P4;
my $P4;
sub get {
return $P4 if $P4;
# ...connection to Perforce server and initialization of $P4 with a P4 object...
return $P4;
}
sub disconnect {
$P4 = $P4->Disconnect() if $P4;
}
sub getFixes {
my $change = shift;
my $p4 = get();
return $p4->Run( "fixes", "-c", $change );
}
在这里,用于在连接到 Perforce 服务器后存储 P4 对象的变量$P4
在脚本开头没有初始化。但是,无论首先调用哪个函数(get
或disconnect
)getFixes
,变量都将在使用之前进行初始化。
这样做有风险吗?我应该$P4
在脚本开头显式初始化变量吗?
解决方案
只是对所提出的基本问题的几个直接答案。
如果“未定义的行为”在 Perl 中意味着某些东西
是的,Perl 中有这样的概念,并且文档警告过它(比 中的频率要低C
)。请参阅脚注†</sup> 中的一些示例。另一方面,在文档中的许多地方,人们发现讨论以
......所以不要那样做。
它经常出现会使解释器感到困惑的事情,并可能导致奇怪且可能无法预测的行为。这些有时是典型的“未定义行为”,即使它们没有直接这样称呼。
主要问题是未初始化的变量如何关联,根据标题和
如果在 Perl 中使用未初始化的变量可能会引发不良行为
这通常不会导致“未定义的行为”,但它当然可能会导致麻烦,并且通常会收到警告。当然,除非变量在这种“使用”中被合法地初始化。例如,
my $x;
my $z = $x + 3;
将为使用$x
而不是为$z
(如果warnings
打开!)绘制警告。请注意,这仍然会成功,因为它$x
被初始化为0
. (但在问题中显示的内容中,代码将在此时中止,因为FATAL
.)
从这个意义上说,问题中显示的代码似乎很好,因为正如你所说
变量将在使用前被初始化
对未初始化的变量进行真值测试很好,因为一旦声明它就配备了 value undef
,在此类测试中是可接受的(和错误的)。
请参阅perlsyn 中的声明中的前几段,以获得关于何时需要或不需要变量的各种摘要defined
。
†</sup> 文档中特别标记为“未定义”的一些行为列表
在标量上下文中调用排序
在列表上下文中,这会对 LIST 进行排序并返回排序后的列表值。在标量上下文中,排序的行为是未定义的。
截断长度太大
如果 LENGTH 大于文件的长度,则行为未定义。
使用不兼容的sysopen标志(无意义)
O_TRUNC
with的行为O_RDONLY
是未定义的。使用kill向进程列表发送信号,其中可以使用负信号或进程号发送到进程组
如果 SIGNAL 和 PROCESS 均为负数,则结果未定义。在未来的版本中可能会产生警告。
-
...在同一语句中修改变量两次将导致未定义的行为。
如果将 hash 插入到中,则使用each进行迭代,尽管它可能很棘手,但表现不佳
如果在迭代时添加或删除散列的元素,对迭代器的影响是未指定的;例如,条目可能会被跳过或重复——所以不要那样做。删除最近返回的项目总是安全的
each
,...这会绘制运行时警告 (F),在 perldiag 中进行了描述
在插入后使用
each()
on hash 而不重置哈希迭代器会导致未定义的行为。语句修饰符 (perlsyn)用于
my
使用语句修饰符条件或循环构造(例如 )修改的 、 或修改
my
的state
行为是未定义的。our
my $x if ...
考虑到 UB 的含义,其中一些似乎有点令人印象深刻(可预测)。感谢 ikegami 的评论。此列表的一部分可在此问题中找到。
从本文发布时的当前文档中撬出(v5.32.1)
推荐阅读
- laravel - 如何防止 Laravel 中不需要的 API 调用
- python - 如何使用 Selenium 和 Python 与基于文本的按钮进行交互
- mysql - 如何选择仅在另一列中包含空值的分组行?
- reactjs - 如何构建按功能或模块拆分的 java 后端和 reactjs 前端项目
- python - 如何迭代具有固定总和的数组集
- sql - 在 GQL 中使用 COUNT
- debugging - Visual Studio代码——lldb调试rust,更改项目目录
- reactjs - React-传单如何在类中创建变量,该变量将根据对象而变化
- android - 如何从 SAF 文件选择器请求中获取文件路径和文件实例?
- android - 如何在 Android 11+ 上使用范围存储访问 /sdcard/Android/media 文件夹?