免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
楼主: neil_young
打印 上一主题 下一主题

web应用mod_perl中的变量申明问题 [复制链接]

论坛徽章:
0
1 [报告]
发表于 2005-11-22 19:43 |显示全部楼层
[quote]原帖由 [i]neil_young[/i] 于 2005-11-22 13:43 发表
我用的是Apache+perl 做的web管理系统,现在碰到几个让我迷惑的事情。
我要在一个pl文件,或者说是那种包内部申明一个私用的包内全局变量。
我举个例子,只是示意,PrintToPage函数是个假定输出到HTML页面上显示 ... [/quote]


从你的问题看,应该可确认你的script运行在mod_perl下。mod_perl与普通cgi最大的不同是,运行在mod_perl下的script只编译一次就被储藏在apache进程里,并继续server后续请求。

另外,一般mod_perl下的脚本都会被相应的Handler进行封装,变成一个包。例如,如果你这里的script运行在Apache::Register下,那它就会被封装在一个package里,这个package只有一个函数,叫做handle(),你的script实际上被wraped在这个handle()函数里。这样,你的script里的子函数changea,实际上就变成了handle()的内嵌子函数。

然后,你的changea子函数使用的变量$a是在子函数之外申明的,这在mod_cgi下不会有什么问题,然而在mod_perl下,这就会造成一个closure。也就是说,changea()里的$a,实际上是外围的my $a的私有拷贝,然而从这一刻起,它就脱离了外围的my申明的变量作用域,看起来就跟一个全局变量一样。

为什么会造成closure?原因就是前面偶提的:一是你的script只编译一次,就储藏在apache进程里;二是你的script实际被wraped成一个package,package里的子函数会通过symbol table的形式export出去,export出去的符号当然不会被原始package里的my申明来初始化。

如果还不明白,可引用programming perl里的example来看看:

sub make_saying {
        my $salute = shift;
        my $newfunc = sub {
                my $target = shift;
                print "$salute, $target!n";
        };
        return $newfunc;     
}

上面的return返回一个匿名函数,这个匿名函数使用了函数外my申明的变量,它实际上是个closure。

$f = make_saying("Howdy");      

初始化,这个过程就相当于你的script在mod_perl下编译的过程。$f就相当于export出来的符号。

然后,不管你怎样访问$f,例如:

$f->("world");
$f->("test");
...

$salute都不会再初始化了,它看起来就跟一个全局变量一样。

当然,如果你再次$g = make_saying("Welcome"); 这等于是重新编译了一次mod_perl脚本,这个符号就改变了。

所以,你的这个子函数:

sub changea
{
PrintToPage "函数内:",$a;
$a=2;
}

从它运行的第一次起,它里面的$a就与外部的my $a脱离了哦,第二次运行时,它会记住上一次的值(因为编译后的code驻留在apache进程里),并且不会被外部的my来初始化了。

讲了这么多,不知你是否明白?偶们的mod_cgi迁移到mod_perl下时,也是经历了好多这样的问题。

解决你这个问题的方法有3个,一是把变量当参数传递,例如:

my $a=1;
changea(1);
sub changea
{
    my $a=shift;
    $a+1;
}

或者用our来申明一个全局的package变量:

our $a=1;
changea();
sub changea
{
    $a+1;
}

或者把你的script定义成package,然后在主script里use或require这个package,这样也可避免问题。

论坛徽章:
0
2 [报告]
发表于 2005-11-22 20:29 |显示全部楼层
原帖由 flw 于 2005-11-22 20:25 发表
仙子好棒哦!
仙子加油~


这种叫法好好听嘛

[ 本帖最后由 flw 于 2005-11-22 20:54 编辑 ]

论坛徽章:
0
3 [报告]
发表于 2005-12-11 21:16 |显示全部楼层
这个帖子偶设为"保留"吧,任何刚接触mod_perl的开发者,都会碰到这个problem的。

另外,如orangetouch所说的,匿名函数并不会导致closure问题,偶想这是因为匿名函数不能构成包的符号的缘故,它export不出去,也就无法通过符号来访问它,故每次都要重新compile了。

[ 本帖最后由 兰花仙子 于 2005-12-11 21:22 编辑 ]
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP