【问题标题】:Can't modify non-lvalue subroutine call in read at download.cgi line 39, near "$cur;"无法修改在 download.cgi 第 39 行“$cur;”附近读取的非左值子例程调用
【发布时间】:2015-12-27 08:32:40
【问题描述】:

您好,我正在尝试编译 perl 程序,但它给出了错误。

这是我的代码

#!/usr/bin/perl

require './filemin-lib.pl';
use lib './lib';

use File::Basename;
use List::Util qw( min max );
use Cwd 'abs_path';

&ReadParse();

get_paths();

my $file = $cwd.'/'.$in{'file'};
my $size = -s "$file";
my $begin=0;
my $end=$size;
(my $name, my $dir, my $ext) = fileparse($file, qr/\.[^.]*/);

open (FILE, "< $file") or die "can't open $file: $!";
binmode FILE;

print "Content-Type: application/x-vlc-plugin\n";
print "Cache-Control: public, must-revalidate, max-age=0";
print "Pragma: no-cache" ;
print "Content-Disposition: attachment; filename=\"$name$ext\"\n";
print "Content-Transfer-Encoding: binary";
print "Accept-Ranges: bytes";
print "Content-Length:  $end - $begin \n\n";
print "Connection: close"; 

#open (FILE, "< $file") or die "can't open $file: $!";
#binmode FILE;

my $cur=$begin;
seek(FILE,$begin,0);
while(!eof(FILE) && $cur < $end)
{
    read FILE, min(1024*16) , $end-$cur;
    $cur+=1024*16;
}
close FILE;

在我试图在vlc-plugin 的帮助下播放视频并且我正在尝试播放视频文件。但我没有找到我出错的地方。但是为此我遇到了错误

Can't modify non-lvalue subroutine call in read at download.cgi line 39, near "$cur;"

请有人帮帮我。在此先感谢。

【问题讨论】:

  • use strict; use warnings; 在脚本开头是非常可取的。
  • 阅读文档:read( FILEHANDLE, SCALAR, LENGTH ) "attempts to read LENGTH characters into variable SCALAR。你应该正确地提供参数:给一个标量来存储,然后一个长度作为参数。他不能存储到min(1024*16)(不是左值)
  • 另外,我确定 for 循环实际上在做什么。也许对您总体上尝试做的事情发表评论会有所帮助。
  • 我正在尝试借助插件播放视频..我无法打开文件
  • 你开启严格和警告了吗?例如,我看不到 %in 被声明。因此,$in{file} 可能没什么用处。

标签: perl


【解决方案1】:

第 39 行必须是这一行:

read FILE, min(1024*16) , $end-$cur;

因为这是$cur; 唯一一次出现在发布的代码中。

如果你查看read的文档,你会发现第二个参数必须是一个标量变量,用于存储读取的数据。

min(1024*16) 不是标量变量。

这是一个函数调用。

正如错误消息所说,所讨论的函数是“非左值子例程”。 “左值”是可以出现在表达式左侧的值,通常意味着左值是可写的。 min 的输出不是。即使是一般情况,也不会出现这种情况,因为min 的输入是一个常量,而常量从不可写。如果是,它们就不会被称为“常数”。

认为你可能想要的是

read FILE, $buf, 1024*16, $end-$cur;

这将从FILE 读取16kb,从$end-$cur 的偏移量开始,并将该数据存储在$buf 中。但你可能一直在尝试在那里做其他事情,所以我可能错了这是你想要的。

我还完全删除了min,因为在单个值上使用它是没有意义的,除非您定义了自己的min 函数,该函数除了返回赋予它的最小值之外的其他值参数。 (如果你有,那么我建议重命名你的函数以避免混淆未来的维护程序员。)

最后,一般 Perl 样板建议:

  • use strict; use warnings; 总是。(除非你有非常具体的理由不这样做,否则你会理解为什么 strict/warnings 不喜欢你正在做的事情,并且你可以清楚地解释为什么你认为无论如何都可以这样做。)

  • 不要在子呼叫前加上&amp; (&amp;ReadParse();)。它是 Perl 4 主义,在 Perl 5 中不再需要,并且具有您可能不知道且几乎肯定不需要的副作用。

  • 使用open 的三参数形式和词法文件句柄,而不是使用旧方法。所以open (my $fh, '&lt;', $file) 而不是open (FILE, "&lt; $file")。当您从用户输入中获取 $file 时,这一点非常重要,这意味着他们可能会向您传递恶意值。

  • 说到这一点,总是在使用它来执行诸如打开文件之类的操作之前对用户输入进行完整性检查。用户输入是不可信的,尤其是在网络上,您应该预期会收到来自试图以创造性方式破坏您的程序的人的恶意输入,这将允许他们对运行它的服务器做不愉快的事情。

  • 最后,有很多非常好的、易于使用的 Web 开发框架,例如 DancerMojolicious。我强烈建议您查看其中之一,而不是滚动您自己的文件下载脚本。而且,如果您尝试制作流式视频(正如提到的 vlc-plugin 提示),那么这比简单的文件下载器还要复杂。

【讨论】:

  • 除了关闭严格和警告之外,您还可以关闭那些您知道妨碍您的东西,然后重新打开它们,例如no strict 'refs;...use strict 'refs'。我从来不需要完全关闭它们,在我的私人脚本中,我有时会做一些很奇怪的事情。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-02-09
  • 2022-01-26
  • 2022-08-19
  • 2014-10-01
  • 1970-01-01
相关资源
最近更新 更多