Пользовательская обработка ошибок перехватывает ошибки, которые обычно не отображаются - PullRequest
2 голосов
/ 10 ноября 2011

У меня проблема, я не могу понять, и надеюсь, что вы, ребята, можете мне помочь.Проблема возникает, когда:

  • Я использую пользовательскую обработку ошибок
  • Я использую File :: Stat в отдельном модуле

Пример:

Основной файл

use strict;
use warnings;

# signal handling
$SIG{__DIE__} = sub {
    my $error = @_;
    chomp $error;
    print "die: $error\n";
};

require mod; 

mod->get_stat();

Модуль

package mod;

use strict;
use warnings;
use File::stat;

sub get_stat {
    my $file_path = "test.txt";
    my $file_size = stat($file_path)->size;
    print $file_size;
}

1;

Это приведет к следующему выводу:

die: 1
die: 1
die: 1
die: 1
die: 1
4

Теперь, если я удалю свою собственную обработку ошибок ИЛИ, если я использую мод вместо требует матрица не будет отображаться.

Интересно видеть, что действительно действительно выдает результат (test.txt составляет 4 байта), что означает stat работает как надо.

Итак, почему я получаю эту ошибку?Это действительно ошибка?Обрабатывает ли по умолчанию обработка ошибок perl ошибки "1"?

EDIT Как заметил Линус Клин, причина, по которой я получаю «1», заключается в том, что я отображаю количество элементов в массиве.

Если вместо этого я распечатываю содержимое ошибки, я получаю следующую ошибку:

die: Your vendor has not defined Fcntl macro S_ISVTX, used at c:/Perl64/lib/File/stat.pm line 37.

die: Your vendor has not defined Fcntl macro S_IFSOCK, used at c:/Perl64/lib/File/stat.pm line 41.

die: Your vendor has not defined Fcntl macro S_IFBLK, used at c:/Perl64/lib/File/stat.pm line 41.

die: S_IFFIFO is not a valid Fcntl macro at c:/Perl64/lib/File/stat.pm line 41.

die: Your vendor has not defined Fcntl macro S_IFLNK, used at c:/Perl64/lib/File/stat.pm line 41.

4

Но, тем не менее, я получаю сообщение об ошибке, которое без пользовательской обработки ошибок я не получаю.

Ответы [ 2 ]

6 голосов
/ 10 ноября 2011

Как объяснено в perlvar , из-за сбоя реализации $SIG{__DIE__} хуки вызываются, даже когда код die s внутри eval . Когда File :: stat загружен, он проверяет, какие константы Fcntl поддерживает на вашей платформе. Он отлавливает ошибки, вызванные неподдерживаемыми константами, но не раньше, чем ваш хук их увидит.

Вы можете определить, находитесь ли вы в eval, проверив значение $^S. Если это не 0, значит, вы в eval.

$SIG{__DIE__} = sub {
    return unless defined $^S and $^S == 0; # Ignore errors in eval
    my ($error) = @_;
    chomp $error;
    print "die: $error\n";
};

Вы не видите ошибок, когда вы use вместо require, потому что use является операцией времени компиляции, а require является операцией времени выполнения (как и установка %SIG). Когда вы use mod и это use s File :: stat, все это происходит за до , вы настраиваете свой хук. Когда вы require mod, этого не произойдет до тех пор, пока после вы не установите хук.

6 голосов
/ 10 ноября 2011

Измените его на

my ($error) = @_;

Вы используете скалярный контекст в своем примере кода, который даст вам количество элементов в @_, то есть один.

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