我正在尝试运行一个perl脚本,其中正在构建一些小树枝。这个脚本应该获取xml文件,并返回作为文件中的一个属性存在的版本号。每次我试图解析一个大文件(23MB)时,脚本都会崩溃,出现以下错误-
"Child 341 terminated with signal 11".
调用子程序的代码,这些子程序将获得所需的属性-
my $version = $strm_obj->get_attr(file=>$file1,tag=>"config",attr=>"contentversion");
print "Version of $file1 is $version n";
my $globalversion = $strm_obj->get_attr(file=>$file2,tag=>"config",attr=>"globalcontentversion");
print "Version of $file2 is $globalversion n";
获取所需属性的子程序-
sub get_attr{
my ($self,%args) = @_;
my $file = $args{file};
my $tag = $args{tag};
my $attr = $args{attr};
my $val;
$self->{_ATTR} = $attr;
$self->{_TAG} = $tag;
test_log(DEBUG,"Value of tag is $tag, attribute is $attr");
my $twig= XML::Twig->new(
twig_roots => { $tag
=> sub {$self->get_attr_helper(@_,$tag,$val); } } )
->parsefile($file);
if ($val){
test_log(INFO,"value of attribute $attr is $val");
}
if (!$val){
test_log(INFO,"The attribute $attr that you are looking for, is not present in $file");
return -1;
}
$twig->purge;
$twig->dispose;
return $val;
}
sub get_attr_helper{
my($self,$obj,$tag,$act_tag,$val) = @_;
my $attr = $self->{_ATTR};
#print "my attr is $attrn";
for my $node ($tag->findnodes("//$self->{_TAG}")){
if ($node->att("$attr")){
$$val = $node->att("$attr");
}
}
$obj->purge;
}
xml文件的格式如下:
$file1-
<config contentversion="378">
<tag1>
.
.
.
<tag n>
</config>
$file2-
<config globalcontentversion="378">
<tag1>
.
.
.
<tag n>
</config>
我在这里无法真正提供实际的xml文件。
我知道这个脚本最多会占用我机器20%的内存(2GB RAM)。
我环顾四周,一直找不到解决这个问题的办法。
如何消除seg故障?
很难给出具体的答案,因为分段故障意味着某个东西正在混乱地崩溃(这是一个基于内存的问题)。
XML很容易占用大量内存,而且在很大程度上,XML::Twig最大的优势之一是它能够使用twig_handlers
和purge
进行解析和丢弃。
这使得它非常适合从XML中部分提取内容。
我看不出是什么给了你一个segfault,但在perl中,你不会经常得到segfault——它很可能是外部的。
除此之外,您似乎正在做一些非常复杂的事情来从文件中提取版本号。(这是假设我没有误读你想要提取的内容)。
这样的东西不适合你的需要吗?:
use strict;
use warnings;
use XML::Twig;
sub get_attr {
my ( $self, %args ) = @_;
my $file = $args{file};
my $tag = $args{tag};
my $attr = $args{attr};
my $twig = XML::Twig->new()->parsefile($file);
my $val = $twig->root->first_child($tag)->att($attr);
#maybe error check to see if 'first_child($tag)' is defined first?
return $val;
}
尽管如果你的"文档根"总是你试图提取的"配置"分支,你可以进一步简化:
my $val = $twig->root->att($attr);
我已经试过了——到目前为止,它对你给出的两个样本都有效。不过,如果你仍然在分段,我会考虑检查你安装了什么。
(使用"树枝处理程序"方法捕获标记可能是值得的,但我认为这不是特别必要的,因为最大的优势是边清除边清除,考虑到问题的规模,这似乎没有必要)。
是XML::Twig:中列出的一个错误
http://search.cpan.org/~mirod/XML-Twig-3.48/Twig.pm#BUGS
解析过程中的segfault当使用5.16之前的Perl版本解析大型文档或许多小型文档时,就会发生这种情况。
这是由于Perl中处理弱引用的方式存在错误。
修复方法是升级到Perl5.16或更高版本(perlbrew是一个很好的工具,可以在同一台机器上管理多个Perl安装)。
另一种不推荐的解决问题的方法是通过编写XML::Twig::_set_weakrefs(0)来关闭弱引用;位于代码顶部。这是完全不支持的,并可能导致其他问题,尽管,
但我不确定这是否适用于您,因为我不会真正称"23MB"为巨大的XML。(甚至要记住,XML的内存占用大约是10倍)。