Пользовательская обработка ошибок — это обнаружение ошибок, которые обычно не отображаются

#perl #file #error-handling #stat

#perl #файл #обработка ошибок #статистика

Вопрос:

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

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

Пример:

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

 use strict;
use warnings;

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

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
  

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

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

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

Редактировать
Как заметил Лайнус Клин, причина, по которой я получаю «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
  

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

Комментарии:

1. require вернет последнюю исполняемую инструкцию из вашего пакета

2. Аааа… Так это Perl, работающий в Windows? Что это за ошибка?

3. Windows 7 с ActivePerl 5.12

Ответ №1:

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

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

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

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

Ответ №2:

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

 my ($error) = @_;
  

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

Комментарии:

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