Почему Perl sysopen сообщает об успехе, но $!есть ошибка? - PullRequest
3 голосов
/ 08 октября 2010

Мой sysopen не работает:

sysopen(DEV, "/dev/ttyS0", O_NONBLOCK|O_RDONLY)

возвращает 1, что успешно!Тогда почему $!есть ошибка «Недопустимый поиск» (где он не определен до вызова)

before sysopen $!:
after sysopen $!: Illegal seek

РЕДАКТИРОВАТЬ: Вот полный сценарий: (используя фактическое значение O_NONBLOCK | O_RDONLY 2048)

 #!/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>;

, который печатает: ./filehandle.pl Незаконный поиск Незаконный поиск ответ от sysopen: 1

Ответы [ 2 ]

16 голосов
/ 08 октября 2010

Так работает переменная C errno.Цитировать из man errno:

Его значение имеет значение только тогда, когда возвращаемое значение вызова указывает на ошибку (то есть -1 в большинстве системных вызовов; -1 илиNULL из большинства библиотечных функций);функция, которая следует за , может изменяться errno.

$! - это просто интерфейс Perl для errno и имеет то же поведение :

Это означает, что значение $! имеет смысл только сразу после сбоя

Необходимо проверить возвращаемое значение sysopen, чтобы определить, не удалось ли это.Если это не удалось, $! скажет вам , почему это не удалось, но вы не можете использовать $!, чтобы определить , это не удалось (если конкретная функция, которую вы используете, не являетсязадокументировано для установки $! на 0. В большинстве случаев нет, включая sysopen).

1 голос
/ 08 октября 2010

Многие подобные специальные переменные в Perl не изменяют свое значение, пока не должны. Вы всегда должны проверять условие, которое фактически установит переменную. Два наиболее распространенных примера - сброс переменных ошибок при возникновении ошибки или сброс переменных захвата регулярного выражения при успешном сопоставлении.

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

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

Это, безусловно, одна из бородавок Perl, поскольку она полагается на побочные эффекты отдаленных глобальных переменных для обозначения того, что произошло локально. В некоторых случаях это даже немного хуже, потому что что-то еще может изменить специальную переменную, прежде чем у вас появится возможность посмотреть на нее, поэтому вы всегда должны проверять ее непосредственно перед выполнением любых других операторов.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...