在一个小测试文件中,我可以运行
#!/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
}
Run Code Online (Sandbox Code Playgroud)
它工作正常.当我在一个更大的程序中运行相同的代码(使用相同的XML输入)时,它终止于
*** glibc detected *** /usr/bin/perl: malloc(): memory corruption: 0x0a40e308 ***
Run Code Online (Sandbox Code Playgroud)
但是,如果我做交换
#open my $xml, "@cmdline |";
my $xml = `@cmdline`;
Run Code Online (Sandbox Code Playgroud)
然后它工作(在两个文件中),所以这更像是一个好奇的问题,而不是一个真正的问题.
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
Run Code Online (Sandbox Code Playgroud)
在大型项目中,和
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
Run Code Online (Sandbox Code Playgroud)
在测试文件中.
更新:我安装了Debian软件包libxml-libxml-perl并$XML::SAX::ParserPackage = "XML::LibXML::SAX";按照建议添加.这也崩溃了,这次有不同的消息:
*** stack smashing detected ***: /usr/bin/perl terminated
Run Code Online (Sandbox Code Playgroud)
但这次它在大文件和小文件中都是一致的.此外,仅在使用时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的答案标记为正确,因为它让我在错误分析中得到了进一步的帮助.谢谢!
XML :: Simple是纯Perl,因此不太可能导致您报告的内存损坏.它取决于较低级别的XML解析器,而且您遇到的错误很可能就在那里.但它可以使用多个解析器,我们需要知道哪一个.
尝试XMLin在示例程序中的行后面添加此行,并使用结果更新您的问题:
print "$_\n" for sort grep /XML/, keys %INC;
Run Code Online (Sandbox Code Playgroud)
这将告诉我们您在系统上实际使用的XML解析器.
如果您还没有安装XML :: LibXML :: SAX,只需安装它就应该将默认的SAX解析器切换到它.如果已安装,请尝试放置
$XML::SAX::ParserPackage = "XML::LibXML::SAX";
Run Code Online (Sandbox Code Playgroud)
在你的程序的开头.(有关如何选择SAX解析器,请参阅XML :: SAX :: ParserFactory.)