В небольшом тестовом файле я могу запустить
#!/usr/bin/perl
use warnings;
use strict;
use open qw{:utf8 :std};
use XML::Simple;
my @cmdline = ("hg", "log", "-v", "--style", "xml");
open my $xml, "@cmdline |";
my $xmllog = XMLin($xml, ForceArray => ['logentry', 'parent', 'copy', 'path']);
foreach my $rev (@{$xmllog->{logentry}}) {
#do stuff
}
, и он отлично работает.Когда я запускаю тот же код в более крупной программе (с тем же вводом XML), он заканчивается на
*** glibc detected *** /usr/bin/perl: malloc(): memory corruption: 0x0a40e308 ***
( полный журнал сбоев @ pastebin.com )
Однако, если я сделаю обмен
#open my $xml, "@cmdline |";
my $xml = `@cmdline`;
, тогда он сработает (в обоих файлах), так что это скорее вопрос любопытства, чем реальной проблемы для меня.
- У кого-нибудь есть указания на то, в чем может быть разница между моим тестовым примером и большей кодовой базой?
- Есть ли скорость / память /?разница в разных вызовах команд?Лучшие практики?
Debian Sid: Perl 5.12.4-1.
(Это моя первая встреча с Perl, поэтому не думайте слишком много о том, что я "должен" знатьо языке. Я просто углубился в существующий код.)
(Большая программа - ikiwiki , так что код не секрет, но я не знаю, где искать проблемыи я не могу включить весь код в этот пост по практическим соображениям. Это касается бэкэнда Mercurial.)
В соответствии с предложением cjm я добавил print "$_\n" for sort grep /XML/, keys %INC;
, который дал вывод
RPC/XML.pm
RPC/XML/Client.pm
RPC/XML/ParserFactory.pm
XML/NamespaceSupport.pm
XML/Parser.pm
XML/Parser/Expat.pm
XML/SAX.pm
XML/SAX/Base.pm
XML/SAX/Exception.pm
XML/SAX/Expat.pm
XML/SAX/ParserFactory.pm
XML/Simple.pm
в большом проекте и
XML/NamespaceSupport.pm
XML/Parser.pm
XML/Parser/Expat.pm
XML/SAX.pm
XML/SAX/Base.pm
XML/SAX/Exception.pm
XML/SAX/Expat.pm
XML/SAX/ParserFactory.pm
XML/Simple.pm
в тестовом файле.
Обновление: Я установил пакет Debian libxml-libxml-perl
и добавил $XML::SAX::ParserPackage = "XML::LibXML::SAX";
как предложено.Это также завершилось с другим сообщением на этот раз:
*** stack smashing detected ***: /usr/bin/perl terminated
full backtrace @ pastebin.com
На этот раз это происходило последовательно как в большом, так и в маломфайл, хотя.Кроме того, только при использовании open
, а не при использовании обратных галочек.
Я также установил libxml-libxml-simple-perl
, но это не должно было быть больше, чем на практике оболочкой, чтобы всегда использовать XML :: LibXML в качестве парсера.Он также вел себя по-разному и жаловался на опции XMLin (), которые были установлены, поэтому я отказался от него.
Попытка явно (и вслепую) заставить программу использовать каждую из альтернатив, предоставленных print "$_\n" for sort grep /XML/, keys %INC;
, кажетсяуказывает на то, что XML :: SAX :: Expat используется по умолчанию, как сказал cjm (поскольку все другие альтернативы завершаются с ошибками, а XML :: SAX: Expat ведет себя точно так же, как исходная проблема в обоих файлах. Явно требующий XML :: Simpleв цикл, который выделяет всю мою память).
Я благодарен за изучение различных синтаксических анализаторов XML и того, что XML :: Simple автоматически выбирает разные.Обе части моего первоначального вопроса несколько остаются:
- Почему программы ведут себя по-разному?Даже если я явно установлю
$XML::SAX::ParserPackage = "XML::SAX::Expat"
в обеих программах, одна аварийно завершает работу (используя open
), а другая работает. - Следует ли использовать другой метод для получения вывода от внешней команды?Даже неправильно ожидать, что XMLin () будет работать с
open
(но почему он работает в одном случае?)?
Или это просто «неправильные» вопросы (т.е. не имеет значения)?
ОБНОВЛЕНИЕ: Прошло больше недели, здесь не было никакой активности, и я решаю ее немного по-другому, без проблем.Я отмечаю ответ cjm как правильный, так как он продвинул меня дальше в анализе ошибок.Спасибо!