为什么Perl';s sysopen报告成功,但美元!有错误吗?

为什么Perl';s sysopen报告成功,但美元!有错误吗?,perl,Perl,我的sysopen失败: sysopen(DEV, "/dev/ttyS0", O_NONBLOCK|O_RDONLY) 返回1,这是一个成功!那么,为什么$!其中有错误“非法搜索”(调用前未定义) 编辑: 下面是完整的脚本:(使用实际的O_NONBLOCK | O_RDONLY值2048) #/usr/bin/perl-w 使用设备::串行端口; 我的$ob; $ob=新设备::串行端口(“/dev/ttyS0”); 打印$!,“\n”; $! = 0; my$ret=sysopen(DEV

我的sysopen失败:

sysopen(DEV, "/dev/ttyS0", O_NONBLOCK|O_RDONLY)
返回1,这是一个成功!那么,为什么$!其中有错误“非法搜索”(调用前未定义)

编辑: 下面是完整的脚本:(使用实际的O_NONBLOCK | O_RDONLY值2048)

#/usr/bin/perl-w
使用设备::串行端口;
我的$ob;
$ob=新设备::串行端口(“/dev/ttyS0”);
打印$!,“\n”;
$! = 0;
my$ret=sysopen(DEV,“/DEV/ttyS0”,2048);
打印$!,“\n”;
$! = 0;
打印“ret from sysopen:”,$ret,“\n”;
#我的$dev=;
打印出: ./filehandle.pl 非法寻找 非法寻找
ret from sysopen:1

这就是C
errno
变量的工作方式。引自:

它的价值只有在 返回值 的调用指示错误(即,most系统的-1) 调用;-1或大多数库函数中的NULL);函数 如果成功,则允许更改
errno

只是Perl与
errno
的接口,具有:

这意味着
$的值是
只有在一个事件之后才有意义
失败


您必须检查sysopen的返回值以确定它是否失败。如果失败,
$
将告诉您失败的原因,但您不能使用
$
来确定它是否失败(除非您正在使用的特定函数被记录为在成功时将
$!
设置为0。大多数都不会,包括
sysopen
)。

Perl中的许多类似特殊变量在不得不更改之前不会更改其值。您应该始终检查实际设置变量的条件。最常见的两个示例是在出现错误时重置错误变量或在成功匹配时重置正则表达式捕获变量

 unless( sysopen( ... ) ) {
      die "Error was $!";
      }

 if( m/(...)(...)/ ) {
      print "Found $1 and $2\n";
      }

这当然是Perl的缺点之一,因为它依赖于远程全局变量的副作用来表示本地发生的事情。在某些情况下甚至更糟糕,因为在您有机会查看特殊变量之前,其他东西可能会更改它,因此您应该在运行任何其他语句之前立即检查它。

您是否看到
sysopen my$ttyh'、/dev/ttyS0',O|NONBLOCK | O|RDONLY或die“无法打开tty:$”的相同行为?始终发布完整的演示脚本。孤立的代码行并没有显示您造成的问题。以太-我与您的建议有相同的错误。这不是他的问题。并不是因为他检查得太晚,而是因为其他原因改变了。成功的函数仍然可以设置
$
设置为某个非空值,但这并不表示函数失败。不过解决方案是相同的。仅在将其设置为有趣值的条件下查看它。这是一个通用的最佳实践。我试着用它作为一个错误检查方法…谢谢你的信息,它帮助了很多。(我用你想要的完整脚本编辑了我的原始帖子)谢谢你指出这一点!我真的一整天都在和它斗争
 #!/usr/bin/perl -w
 use Device::SerialPort;
 my $ob;

 $ob = new Device::SerialPort("/dev/ttyS0");

 print $!, "\n";
 $! = 0;

 my $ret = sysopen(DEV, "/dev/ttyS0", 2048);

 print $!, "\n";
 $! = 0;

 print "ret from sysopen: ", $ret, "\n";
 #my $dev = <DEV>;
 unless( sysopen( ... ) ) {
      die "Error was $!";
      }

 if( m/(...)(...)/ ) {
      print "Found $1 and $2\n";
      }