免费注册 查看新帖 |

Chinaunix

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

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

论坛徽章:
0
11 [报告]
发表于 2005-11-22 15:01 |只看该作者
晕啊,是我问你啊,还是你问我啊?
我用这种方法执行也是对的,但通过浏览器apache访问就不一样了,
所以我在怀疑应该是这之间出的问题

论坛徽章:
1
2015年辞旧岁徽章
日期:2015-03-03 16:54:15
12 [报告]
发表于 2005-11-22 15:09 |只看该作者
算了。你自己折腾吧。
不要期望我有和你一样的环境,我这里只能这样了。

论坛徽章:
0
13 [报告]
发表于 2005-11-22 15:10 |只看该作者
看不懂你的程序,
  1. our $abc;
  2. writelog($abc);
复制代码

还没有给变量赋值就去writelog了,到底想测试什么哩?
预期结果应该是打印出
初始:1
函数内:1
结束:2

我在IE里访问该pl文件,第一次执行后,得到了预期结果,可当我再次执行这个pl时,却得到了
初始:1
函数内:2
结束:1

你又不是写的网站计数器程序,怎么会这样哩?是不是因为没有给变量初始化啊?你再仔细查查看!

论坛徽章:
1
2015年辞旧岁徽章
日期:2015-03-03 16:54:15
14 [报告]
发表于 2005-11-22 15:21 |只看该作者
呵呵,我理解楼主。
他的程序可能比较大,而且他现在还没有定位到问题在哪儿。
自然也就复显不了。
随便编个小程序,逗大家玩会儿,其实心里还是在想着如何自己独立去解决。
楼主,加油!

BTW:Perl 的语法可以参考《Perl 语言编程》上面写得很清楚的。
local 和 my 还有 our 的用法,从这个 BBS 搜索一下,以前讨论过。
兰花仙子的个人专集里有她写的。
我自己也回复过,阐述地都很精彩、很清楚。

论坛徽章:
0
15 [报告]
发表于 2005-11-22 15:23 |只看该作者
这个问题讲起来挺多话的,因为在mod_perl下,你的程序陷入了所谓的closure。
等兰花仙子有空跟你讲吧。

论坛徽章:
1
2015年辞旧岁徽章
日期:2015-03-03 16:54:15
16 [报告]
发表于 2005-11-22 15:41 |只看该作者
原帖由 af80 于 2005-11-22 15:23 发表
这个问题讲起来挺多话的,因为在mod_perl下,你的程序陷入了所谓的closure。
等兰花仙子有空跟你讲吧。

你是个坏蛋!
我不懂 mod_perl,但是隐隐约约记得它似乎比较特殊。
而且仙子上回也碰到过这个问题。
closure 是闭包吗?呵呵。
WEB 程序我就真的不懂了……
毕竟 mod_perl 不是我学的 Perl,呵呵。

论坛徽章:
0
17 [报告]
发表于 2005-11-22 17:46 |只看该作者
原帖由 af80 于 2005-11-22 15:23 发表
这个问题讲起来挺多话的,因为在mod_perl下,你的程序陷入了所谓的closure。
等兰花仙子有空跟你讲吧。


看来大致的原因并非是perl本身的问题,要等花仙子姐姐有空来讲了。
谢谢大家的热心!!

版主这儿能不能发一些技术无关的贴子?我想问一下大家在国内用perl的都拿来干什么的啊。

对了还有这贴子里特殊字符,这算是论坛的BUG吧,得不得修修啊?
特别是咱们老贴程序代码。有不少特殊字符都不能正常显示

[ 本帖最后由 neil_young 于 2005-11-22 17:48 编辑 ]

论坛徽章:
0
18 [报告]
发表于 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,这样也可避免问题。

论坛徽章:
1
2015年辞旧岁徽章
日期:2015-03-03 16:54:15
19 [报告]
发表于 2005-11-22 20:25 |只看该作者
仙子好棒哦!
仙子加油~

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

论坛徽章:
0
20 [报告]
发表于 2005-11-22 20:29 |只看该作者
原帖由 flw 于 2005-11-22 20:25 发表
仙子好棒哦!
仙子加油~


这种叫法好好听嘛

[ 本帖最后由 flw 于 2005-11-22 20:54 编辑 ]
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

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

清除 Cookies - ChinaUnix - Archiver - WAP - TOP