を特定することはできません、私はファイルハンドルとXML :: Simple-> Memory corruption。小さなテストファイルでは問題
#!/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 ***
(full crash log @ 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
それはしかし、大小のファイルの両方に一貫して起こったこの時間:これはまた別のメッセージこの時点で、墜落しました。また、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"
を設定しても、1つがクラッシュし(open
を使用)、他のプログラムが動作します。 - 外部コマンドから出力を受け取る別の方法を使用する必要がありますか?
open
でXMLin()の仕事を期待するのは間違っていますか(しかし、なぜそれは1つのケースで動作しますか?)
「または間違っている」質問は簡単ですか(無関係)?
UPDATE:一週間以上は、ここでは、活動のない突風を通過した、と私は問題もなく、今少し違っそれを解決します。私はcjmの答えを正しいとマークしています。なぜなら、それはエラー分析の中でさらに私を得ているからです。ありがとう!
「オープン」を使用するのはなぜですか? XMLはutf-8でエンコードされていません。 XMLはバイナリで、エンコーディングを検出するのはパーサーに任されています。これが '<?xml'の目的です。 (これにより、パーサーは、文字セットを読むためのエンコーディングについての十分な情報を得ます。宣言は、実際にドキュメントを解析するために使用されます)。もちろん、セグメンテーションを引き起こすべきではありません。 'use open'を削除し、何が起こるかを見てください。 – jrockway
また注目に値する:私はXML :: ParserのXSコードをすばやく見て、 "utf8フラグ"を使って非常に高速で遊ぶことに気づいた。バッファが有効かどうかにかかわらずフラグをオンにするutf8。 XML :: LibXMLを使用してください:) – jrockway
"openを使用する"は、大きなプログラムで既に使用されていたヘッダーを再作成することだけでした。私は問題を分離するために環境を可能な限り等しくしたいと思っていましたが、そうではありませんでした。 –