Файловые дескрипторы и XML :: Simple -> Повреждение памяти.Не могу выделить проблему - PullRequest
2 голосов
/ 25 июля 2011

В небольшом тестовом файле я могу запустить

#!/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`;

, тогда он сработает (в обоих файлах), так что это скорее вопрос любопытства, чем реальной проблемы для меня.

  1. У кого-нибудь есть указания на то, в чем может быть разница между моим тестовым примером и большей кодовой базой?
  2. Есть ли скорость / память /?разница в разных вызовах команд?Лучшие практики?

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 автоматически выбирает разные.Обе части моего первоначального вопроса несколько остаются:

  1. Почему программы ведут себя по-разному?Даже если я явно установлю $XML::SAX::ParserPackage = "XML::SAX::Expat" в обеих программах, одна аварийно завершает работу (используя open), а другая работает.
  2. Следует ли использовать другой метод для получения вывода от внешней команды?Даже неправильно ожидать, что XMLin () будет работать с open (но почему он работает в одном случае?)?

Или это просто «неправильные» вопросы (т.е. не имеет значения)?


ОБНОВЛЕНИЕ: Прошло больше недели, здесь не было никакой активности, и я решаю ее немного по-другому, без проблем.Я отмечаю ответ cjm как правильный, так как он продвинул меня дальше в анализе ошибок.Спасибо!

1 Ответ

5 голосов
/ 25 июля 2011

XML :: Simple является чисто Perl, поэтому вряд ли это приведет к повреждению памяти, о котором вы сообщаете.Это зависит от низкоуровневого синтаксического анализатора XML, и, скорее всего, там есть ошибка, с которой вы столкнулись.Но есть несколько синтаксических анализаторов, которые он может использовать, и нам нужно знать, какой именно.

Попробуйте добавить эту строку сразу после строки XMLin в вашей программе примера и обновите свой вопрос с результатами:

print "$_\n" for sort grep /XML/, keys %INC;

Это скажет нам, какой анализатор XML вы фактически используете в своей системе.


Обновление: Поскольку, похоже, вы используете XML :: Parser (через его интерфейс SAX XML :: SAX :: Expat , яЯ рекомендую попробовать XML :: LibXML :: SAX * 1017. * Libxml2 считается одним из лучших анализаторов XML.

Если у вас еще не установлен XML :: LibXML :: SAX,просто установите его, чтобы переключить на него используемый по умолчанию SAX-анализатор. Если он установлен, попробуйте поставить

$XML::SAX::ParserPackage = "XML::LibXML::SAX";

в начале вашей программы. (См.

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