在一个小的测试文件中,我可以运行
#!/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 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"
在两个程序中都明确设置,一个崩溃(使用open
)而另一个工作。 - 我应该使用另一种方法来接收来自外部命令的输出吗?期望 XMLin() 可以使用它甚至是错误的
open
(但是为什么它在一种情况下可以工作呢?)?
或者它们是简单的“错误”问题(即不相关)?
更新:一个多星期过去了,这里没有一连串的活动,我现在解决它有点不同,没有问题。我将 cjm 的答案标记为正确,因为它让我在错误分析中更进一步。谢谢!