小さなテストファイルで実行できます
#!/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 ***
でも、両替をしたら
#open my $xml, "@cmdline |";
my $xml = `@cmdline`;
その後、(両方のファイルで)機能するため、これは私にとって実際の問題というよりも好奇心の問題です。
- 私のテストケースとより大きなコードベースとの違いについて誰かが何かポインタを持っていますか?
- 速度/メモリ/はありますか? 異なるコマンド呼び出しの違いは? ベストプラクティス?
Debian シド: 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
ただし、今回は大きなファイルと小さなファイルの両方で一貫して発生しました。また、open
バッククォートを使用する場合ではなく、使用する場合のみ。
もインストールlibxml-libxml-simple-perl
しましたが、これは実際には常に XML::LibXML をパーサーとして使用するためのラッパー以上のものではないはずでした。また、動作が異なり、設定されている XMLin() のオプションについて不平を言ったので、破棄しました。
明示的に (そしてやみくもに) によって与えられた代替手段のそれぞれをプログラムに使用させようとするとprint "$_\n" for sort grep /XML/, keys %INC;
、cjm が言ったように、XML::SAX::Expat がデフォルトで使用されることを示しているようです (他のすべての代替手段はエラーで終了し、XML::SAX のため) :Expat は、両方のファイルで元の問題とまったく同じように動作します. 明示的に要求する XML::Simple は、すべてのメモリを割り当てるループに入ります)。
さまざまな XML パーサーについて学び、XML::Simple がさまざまなパーサーを自動的に選択してくれることに感謝しています。ただし、元の質問の両方の部分が多少残っています。
- プログラムの動作が異なるのはなぜですか? 両方のプログラムで明示的に設定
$XML::SAX::ParserPackage = "XML::SAX::Expat"
しても、一方がクラッシュし (を使用open
)、もう一方が動作します。 - 外部コマンドからの出力を受け取るために別の方法を使用する必要がありますか? XMLin() が動作することを期待するのは間違ってい
open
ますか?
それとも、単純に「間違った」質問をしているだけですか (つまり、無関係ですか) ?
更新: 1 週間以上が経過しましたが、ここでは慌ただしい活動はありませんでした。問題なく解決しました。エラー分析をさらに進めることができたので、cjm の回答を正しいものとしてマークします。ありがとう!