Программист написал функцию, которая должна читать файл и возвращать его содержимое и размер.
use File::Slurp;
# Получает имя файла,
# читает файл и его метаданные,
# возвращает ссылку на хеш { filename => '...', content => '...', size => NNN }.
# Если файл не существует, content и size равны undef
sub read_file_with_metadata
{
my ($filename) = @_;
my @stat = stat $filename;
return {
filename => $filename,
content => eval {scalar read_file($filename)},
size => $stat[7],
};
}
И все бы хорошо, но иногда в поле content
оказываются совершенно неправильные значения.
Пример кода можно скачать и поотлаживаться локально.
Это происходит, когда функция получает имя несуществующего файла.
Результат в этом случае получается такой:
{
'' => undef,
filename => '<nonexistent_file>',
content => 'size'
};
Проблема в eval
, которым обернут вызов read_file
.
Если код внутри eval
выполняет die
, то eval
возвращает
undef
в скалярном контексте и пустой список в списковом контексте.
Таким образом, если файл не существует, возвращаемое значение функции превращается в
{
filename => $filename,
content => 'size',
$stat[7],
}
, а это, конечно, не то, что задумывалось.
Кстати, если бы программист использовал прагму warnings
, он мог бы заметить предупреждение
Odd number of elements in anonymous hash
Короткое исправление могло бы быть таким:
- content => eval {scalar read_file($filename)},
+ content => scalar eval {scalar read_file($filename)},