几年来我一直在使用apache mod_cgi。现在我转向mod_perl,我发现了一些问题,特别是子程序。到现在为止,我从未使用my
,our
或local
;并且CGI脚本没有问题。在阅读了文档甚至是此处发布的一些先前问题后,我或多或少了解my
,our
和local
的工作原理。我担心的是下一个请求之间将共享哪些信息(如果我理解正确的话,这是我在运行mod_perl而不是mod_cgi时必须具备的主要问题)。
our
还是仅使用标量而不声明my
等特殊内容之间是否有任何区别?不是全球性的吗?my
内的标量中使用if
,之后我创建另一个if
我使用的if
相同的标量;是if
或每个while
之间共享的标量意味着不同的块?那么for
和my
呢,它们是先前声明为{{1}}标量的不同块,还是仅适用于子程序和文件? 答案 0 :(得分:17)
mod_perl 的工作方式是将每个Perl脚本包装在一个名为handler
的子例程中,该子例程基于脚本的名称和路径。而不是启动一个新进程来运行每个脚本,这个handler
子例程由许多持久的Perl theads中的一个调用。
通常这些知识可以帮助理解来自 mod_cgi 的环境变化,但是因为你从未在程序中添加use strict
并熟悉声明变量的工作原理有很多事情要做!
mod_perl 环境有可能导致非明显的安全漏洞,您现在应该开始{em>每个脚本上的use strict
并声明每个变量。 use Carp
还可以帮助您了解错误日志。
使用our
声明的变量名是具有相同名称的包变量的词法范围同义词,可以在不通过包含包名完全限定名称的情况下使用该变量。例如,通常使用our $var
声明的变量将提供对$main::var
标量的访问(如果没有前面的package
声明),而不指定main::
。但是,在 mod_cgi 中以undef
值开始生效的变量现在将保留其先前执行任何给定 mod_perl 线程的值,并保持一致性在声明时总是初始化它们是最安全的。另请注意,由于 mod_perl 的包装,默认包名称不再是main
,因此您无法再使用main::
前缀访问包变量,它是不明智地找到包的实际名称并明确使用它,因为它将是非常长名称,并且如果您移动或重命名脚本将会更改。
my
变量是独立于包符号表存在的变量,通常其生命周期是封闭文件(对于在文件范围内声明的变量)或子例程的运行时间。如果在脚本的文件范围内声明和使用它们,或者完全在一个子例程中,它们在 mod_perl 中都是安全的,但是如果混合范围并在文件范围内声明my $global
,则可能会受到攻击。然后尝试在子程序中使用它。这样做的原因并不简单,但它是由 mod_perl 将脚本包装在handler
子例程中引起的,因此您有嵌套的子例程声明。内部子例程将倾向于仅采用$global
的第一个实例化,并忽略稍后调用handler
创建的任何其他实例。如果您需要一个全局变量,您应该使用our
声明它并在该声明中初始化它,如上所述。
local
变量非常类似于our
变量,因为它形成了包变量的同义词。但是,它会暂时保存该变量的当前值,并提供一个新副本以供使用,直到文件或块作用域结束。由于它在其范围内自动创建和删除,因此它可以替代 mod_perl 脚本中的my
变量,特别是在使用指向数据结构的指针时,例如,实例CGI
类的。{声明our $cgi = CGI->new
会正确创建对象,但由于 mod_perl 持久性,会将其留在内存中,直到线程的下一次执行删除它为另一个执行腾出空间。
关于你的问题:
如果use strict
到位,则使用变量而不声明它会导致编译时错误。否则,它是当前包命名空间中该变量的同义词。
变量是包变量或词法变量;没有办法将变量声明为 private 。除非您通过编写使用在更广泛的范围,当变量将持久但不会做你想要的。使用my
声明的变量将在脚本调用之间保留其值,而使用our
声明的变量将在脚本终止时被销毁。 local
和our
变量都是包变量,对同一变量名的所有引用都引用相同的变量。
要声明在脚本的任何一次调用中始终可访问的变量,您可以使用local
变量或初始化的local
变量。文件范围our
在很大程度上等同于 mod_perl 脚本的local $global
。如果您使用our $global = undef
变量指向数据结构,请记得使用our
在脚本末尾销毁它。
undef $global
变量对于声明它们的块是唯一的,并且在其中可见,无论是my
,if
还是{{1或者甚至只是一个裸while
块范围。始终将for
变量用于临时工作变量,这些变量仅在块中使用,并且可以从其他任何地方访问。
我希望这会有所帮助
答案 1 :(得分:8)
编辑:这是关于Perl变量范围的一般信息。有关具体的mod_perl
问题,请参阅Borodin的帖子。
用my
声明的变量是词法。换句话说,它们仅存在于当前范围内。您应该默认使用my
声明所有变量;当你特别想要不同的功能时,只做别的事。
使用词法范围的变量是(几乎)任何语言的良好代码设计的基本部分。将use strict;
和use warnings;
放入所有脚本中将需要您遵循此良好做法。
our
是一种声明全局变量的方法;底层结果与使用未声明的全局变量非常相似。但是,它有两点不同:
use strict;
,也可以通过这种方式创建全局。our
声明的变量可以通过您在当前范围内的所有包中声明的名称访问。相反,未声明的变量只能通过当前包中的简单名称访问。除此之外,您只能将其称为$package::variable
。有关详细信息,请参阅the documentation for our
。
local
不会创建词法变量;相反,它是一种在当前范围内为全局变量赋予临时值的方法。它主要与Perl的特殊内置(标点符号)变量一起使用:
{
local $/; #make the record separator undefined in this scope only.
my $file = <FILE>; #read in an entire file at once.
}
您可以随时使用my
始终使用local
进行变量,并仅将{{1}}用于上述特殊情况。