在一个小测试文件中,我可以运行
#!/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解析器。我原来问题的两个部分都有些保留:
$XML::SAX::ParserPackage = "XML::SAX::Expat"
,一个崩溃(使用open
),另一个工作。open
一起工作甚至是错误的(但为什么它在一个案例中起作用呢?)?或者他们简单地提出要求的“错误”问题(即不相关)?
更新:超过一个星期过去了,而不是一连串的活动,我现在解决它有点不同,没有问题。我将cjm的答案标记为正确,因为它让我在错误分析中得到了进一步的帮助。谢谢!
答案 0 :(得分:5)
XML::Simple是纯Perl,因此不太可能导致您报告的内存损坏。它取决于较低级别的XML解析器,而且您遇到的错误可能就在那里。但是它可以使用多个解析器,我们需要知道哪一个。
尝试在示例程序的XMLin
行后面添加此行,并使用结果更新您的问题:
print "$_\n" for sort grep /XML/, keys %INC;
这将告诉我们您在系统上实际使用的XML解析器。
<小时/> 更新:由于看起来您正在使用XML::Parser(通过其SAX界面XML::SAX::Expat,我建议您尝试使用XML::LibXML::SAX .Libxml2被认为是更好的XML解析器。
如果您还没有安装XML :: LibXML :: SAX,只需安装它就可以将默认的SAX解析器切换到它。如果已安装,请尝试添加
$XML::SAX::ParserPackage = "XML::LibXML::SAX";
在您的计划开始时。 (有关如何选择SAX解析器,请参阅XML::SAX::ParserFactory。)