【问题标题】:Perl script with XML Twig seg faulting, child terminated with signal 11带有 XML Twig 段错误的 Perl 脚本,子进程以信号 11 终止
【发布时间】:2014-01-20 13:35:40
【问题描述】:

我正在尝试运行一个 perl 脚本,其中构建了一些树枝。 此脚本应获取 xml 文件并返回作为文件中的属性存在的版本号。 每次我尝试解析一个大文件(23 MB)时,脚本都会崩溃并显示以下内容 -

"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 $attr\n";
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)。

我环顾四周,找不到解决办法。

如何消除段错误?

【问题讨论】:

  • 您的程序是否会因twig_roots =&gt; { '/config' =&gt; 1 } } 等更简单的内容而崩溃?
  • 您希望您的脚本有什么样的输出?看起来您正在获取单个元素然后丢弃其余元素?

标签: xml perl xml-parsing segmentation-fault xml-twig


【解决方案1】:

很难给出一个具体的答案,因为分段错误意味着某些东西混乱不堪(这是一个基于内存的问题)。

XML 很容易占用大量内存,XML::Twig 的最大优势之一是它能够使用twig_handlers 和purge 进行解析和丢弃。

这使得它非常适合从 XML 中提取部分内容。

我看不出具体是什么给了你一个段错误,但是 - 在 perl 中,你不会经常遇到段错误,它可能是外部的。

除此之外,您似乎正在做一些相当复杂的事情来从文件中提取版本号。 (这是假设我没有误读您要提取的内容)。

这样的东西不适合您的需要吗?:

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);

我已经尝试过了 - 它适用于您目前提供的两种样品。如果您仍然存在段错误,我会考虑检查您已安装的内容。

(可能值得采用 'twig handlers' 方法来捕获标签,但我认为这不是特别必要的,因为最大的优势是随时清除,鉴于问题的大小)。

有在 XML::Twig: 中列出了一个错误:

http://search.cpan.org/~mirod/XML-Twig-3.48/Twig.pm#BUGS

解析期间的段错误 使用 5.16 之前的 Perl 版本解析大型文档或大量小型文档时会发生这种情况。

这是由于 Perl 本身处理弱引用的方式存在错误。

修复方法是升级到 Perl 5.16 或更高版本(perlbrew 是管理同一台机器上多个 perl 安装的好工具)。

另一种不推荐的解决问题的方法是通过编写 XML::Twig::_set_weakrefs(0); 来关闭弱引用。在代码的顶部。这是完全不受支持的,但可能会导致其他问题,

不过,我不确定这是否适用于您,因为我不会真正将“23MB”称为巨大的 XML。 (即使记住 XML 的内存占用大约是 10 倍)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-03-27
    • 1970-01-01
    • 2014-10-11
    相关资源
    最近更新 更多