6

几年来我一直在使用 apache mod_cgi。现在我正在转向 mod_perl,我发现了一些问题,特别是子例程。直到现在我从来没有使用过my,our也没有local; 并且 CGI 脚本可以正常工作。my在阅读了文档甚至之前发布的一些问题之后,我或多或少地了解了它是如何工作ourlocal。我关心的是下一个请求之间将共享哪些信息(如果我理解正确,这是我在运行 mod_perl 而不是 mod_cgi 时必须关心的主要问题)。

  • our在标量中使用或仅在标量中使用而不声明任何特殊内容(例如 )有什么区别my?不是都是全球性的吗?
  • 如果我不将标量声明为私有,是否将在下一个请求中共享?即使在同一服务器中另一个不同 perl 脚本的请求中?
  • 如何将子例程内的标量值共享到该子例程外部但不在同一文件或同一请求之外?
  • 如果我在文件的同一级别或同一子例程my中的一个标量中使用 a,然后我在使用相同标量的地方创建另一个;两者或每个之间共享的标量是否意味着不同的块?和,它们是先前声明为标量的不同块还是仅适用于子例程和文件?ififififwhileformy
4

2 回答 2

17

mod_perl的工作原理是将每个 Perl 脚本包装handler在一个基于脚本名称和路径的包内调用的子例程中。这个子例程不是启动一个新进程来运行每个脚本,而是handler由许多持久的 Perl 线程中的一个调用。

通常,这些知识将有助于理解mod_cgi中的环境变化,但是由于您从未添加use strict到程序中并且熟悉声明变量的工作原理,因此您还有很多工作要做!

mod_perl环境有可能导致不明显的安全漏洞,您现在应该开始处理use strict每个脚本并声明每个变量。use Carp还将帮助您了解错误日志。

声明的变量名our是同名包变量的词法范围同义词,可以在不完全限定名称的情况下通过包含包名来使用。例如,通常用 声明的变量our $var将提供对$main::var标量的访问(如果之前没有package声明)而无需指定main::. undef然而,这些以in mod_cgi值开始生命的变量现在将保留它们在任何给定mod_perl线程的先前执行中的值,并且为了保持一致性,始终在声明点初始化它们是最安全的。另请注意,默认包名称不再main是因为包装了mod_perl确实如此,因此您不能再使用main::前缀访问包变量,并且找到包的实际名称并明确使用它是不明智的,因为它将是一个非常长的名称,并且会在您移动或重命名脚本时发生变化。

my变量是独立于包符号表而存在的变量,通常它的生命周期是封闭文件(对于在文件范围内声明的变量)或子例程的运行时间。如果在脚本的文件范围内或完全在一个子例程中声明和使用它们,它们在mod_perl中是安全的,但如果您混合范围并my $global在文件范围内声明 a 然后尝试在子例程中使用它,您可能会被刺痛。原因并不简单,而是由于mod_perl将您的脚本包装在一个handler子例程中,因此您有嵌套的子例程声明。内部子例程将倾向于只采用第一个实例化$global并忽略由以后调用创建的任何其他handler. 如果您需要一个全局变量,您应该使用它声明它our并在该声明中初始化它,如上所述。

变量与local变量非常相似our,因为它是包变量的同义词。但是,它会临时保存该变量的当前值并提供一个新副本以供使用,直到文件或块范围结束。由于它在其范围内自动创建和删除,它可以成为mod_perlmy脚本中变量的有用替代方案,特别是在您使用指向数据结构(例如类的实例)的指针的情况下。声明将正确创建对象,但由于mod_perl 的持久性,会将其留在内存中,直到线程的下一次执行将其删除以腾出空间给另一个对象。CGIour $cgi = CGI->new

至于你的问题:

  • 使用变量而不声明它会导致编译时错误,如果use strict它应该是适当的。否则,它是当前包命名空间中该变量的同义词。

  • 变量要么是包变量,要么是词法变量;没有办法将变量声明为私有的。my每次执行脚本时都会创建和销毁词法变量用不要做你想做的事。声明为 with 的变量our将在调用脚本时保留其值,而声明为 with的变量将local在脚本终止时销毁。our和变量都是local包变量,所有对同一个变量名的引用都指向同一个变量。

  • 要声明一个在脚本的任何一次调用中随处可访问的变量,您可以使用local变量或初始化our变量。在文件范围内local $global很大程度上等同our $global = undefmod_perl脚本。如果您使用our变量指向数据结构,请记住在脚本末尾使用undef $global.

  • my变量在声明它们的块中是唯一的,并且在其内可见,无论该块是ifwhile或内的块for,甚至只是一个裸{ ... }块范围。始终将my变量用于临时工作变量,这些变量仅在块内使用且无法从其他地方访问。

我希望这有帮助

于 2012-10-23T08:27:01.680 回答
8

编辑:这只是关于 Perl 变量作用域的一般信息。mod_perl有关具体问题,请参阅 Borodin 的帖子。

声明的变量my是词法的。换句话说,它们只存在于当前范围内。您应该my默认声明所有变量;仅当您特别想要不同的功能时才做其他事情。

使用词法范围的变量是(几乎)任何语言中良好代码设计的基本部分。放入所有脚本将要求您遵循此良好实践use strict;use warnings;

our是一种声明全局变量的方式;底层结果与使用未声明的全局变量非常相似。但是,它有两个不同之处:

  1. 您明确声明您希望变量是全局的。这是一个很好的做法,因为使用全局变量应该是一个例外情况。因此,即使use strict;.
  2. 声明的变量our将可以通过您在当前范围内的所有包中声明的名称访问。相比之下,未声明的变量只能通过当前包中的简单名称访问。除此之外,您只能将其称为$package::variable.

有关更多详细信息,请参阅文档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仅用于上面所示的特殊情况来走得更远。

于 2012-10-23T08:26:18.277 回答