2014-10-22 2 views
1

Я получаю ошибку:Ошибка "паника: попытка скопировать освобожденный скаляр" при использовании Getopt :: Long

panic: attempt to copy freed scalar a121fb4 to a156be8 at ./p.pl line 13. 

когда я запускаю следующую программу (p.pl):

use warnings; 
use strict; 
use Getopt::Long qw(GetOptions); 

main(@ARGV); 

sub main { 
    GetOptions(); 

    print "\@[email protected]\n"; 
    my $arg=shift; 
} 

при использовании один или несколько аргументов командной строки, например p.pl 1 дает ошибку.

В чем причина этого?

+1

Почему вы называете «GetOptions» без аргументов? Почему вы не проверяете возвращаемое значение «GetOptions»? Почему вы передаете '@ ARGV'' main'? В этом коде есть много сомнительных практик. – toolic

+0

'shift' работает на' @ _' внутри под. – toolic

+0

Какую версию Perl (и платформы) вы используете? Это работает без ошибок на Perl 5.16.3 в Linux Debian Wheezy. Обновление: я забыл добавить аргумент; Я тоже получаю эту ошибку. –

ответ

4

Это ошибка, которая возникает из-за того, что вы проходите @ARGV.

@_ присвоен псевдонимам значений @ARGV. GetOptions затем выполняет операции с оригиналом @ARGV, поэтому у вас возникли проблемы с shift @_.

Вот два решения.

  1. Выполните GetOptions перед вызовом суб:

    GetOptions(); # Manipulate @ARGV before passing it. 
    
    main(@ARGV); 
    
    sub main { 
        print "\@[email protected]\n"; 
        my $arg = shift; 
    } 
    
  2. Не беспокоить прохождения @ARGV, потому что это глобальное все равно:

    main(); # Don't pass @ARGV since it's global 
    
    sub main { 
        GetOptions(); 
    
        print "\@[email protected]\n"; 
        my $arg = shift @ARGV; 
    } 
    
+2

Почему вы называете «GetOptions» без аргументов? Это похоже на неправильное использование функции. – toolic

+0

Я за то, что OP сделал. Никакой другой причины. Почему ты? Поскольку вы все равно можете выполнить проверку ошибок, ища неожиданные аргументы командной строки. Да, ему нужно добавить «или умереть», но, возможно, он удалил их при создании «MCVE». – Miller

+0

Интересно, что с помощью ссылки (или просто 'print \ @_') перед вызовом функции исключается ошибка. –

0

Я считаю, что детали я просто отправляемые как «запрос об ошибке обхода» в Getopt :: Long будет помочь прояснить эту ситуацию:

https://rt.cpan.org/Ticket/Display.html?id=120562

Это чувствительное для запуска: без «моего $ а» ошибка, перестает появляться.

Post Scriptum: Я понимаю Getopt :: Long упоминает @ARGV много раз в своей документации, с такими замечаниями, как «@ARGV всегда будет пуст после успешного возвращения GetOptions()». «Временное» решение обхода может быть для Getopt :: Long, чтобы предупредить об этом явном ошибке Perl, и программисты должны использовать вместо Getopt :: Long :: GetOptionsFromArray ([@ ARGV]), если они хотят иметь возможность использовать @ARGV после Getopt :: Долгое использование.

Смежные вопросы