sco*_*ozy 6 perl segmentation-fault
我一定perl
非常沮丧,因为它给了我一个错误信息,没有记录在perldiag
:
PmmREFCNT_dec:对于53a6930,REFCNT递减到0以下!
根据其情绪,有时会出现以下情况:
***glibc检测到***/usr/bin/perl:双重免费或损坏(!prev):0x0000000004e58a60 *
......或更明显地:
分段故障
这显然是致命的,但我也测试过它是可以捕获的.使用时Try::Tiny
,我将始终在同一位置捕获错误,但在不使用它时,会在崩溃发生之前执行更多指令.此外,即使我的模块完全是确定性的,并且我非常确定所有依赖关系也是如此,但错误不会一直发生.
不幸的是,给我这个问题的模块是巨大的,有很多依赖,我无法在一个较小的例子上复制问题.因此,我不能请求帮助调试它,但如果熟悉Perl内部的人知道在什么情况下发生此错误,这可能有助于我(或任何其他人将看到此消息)找到问题的根源和/或解决方法.
如果有用,一般的想法是这样的.我有两个班,让我们称他们Thing
和SetOfThings
.SetOfThings
有一个属性是一组Thing
实例.这两个类都有一个explode
类似这样的方法:
# SetOfThings
sub explode {
my $self = shift;
my $new = dclone $self;
delete $new->{'some_attribute'};
$new->set_of_things( map { $_->explode } $self->constraints );
return $new;
}
# Thing
sub explode {
my $self = shift;
return map { new Thing( do_something_fancy ) } keys %$self;
}
Run Code Online (Sandbox Code Playgroud)
通常在调用SetOfThings::explode
或调用SetOfThings::set_of_things
getter 时会出现错误.
编辑:Backtrace
我不相信我有足够的能力解释它,但我从gdb
以下地方获得了回溯:
#0 0x00007ffff70a6094 in ?? () from /lib/x86_64-linux-gnu/libc.so.6
#1 0x00007ffff70a76a8 in ?? () from /lib/x86_64-linux-gnu/libc.so.6
#2 0x00007ffff70aab1c in free () from /lib/x86_64-linux-gnu/libc.so.6
#3 0x00007ffff7b0869b in Perl_hv_undef_flags () from /usr/lib/libperl.so.5.14
#4 0x00007ffff7b1ae66 in Perl_sv_clear () from /usr/lib/libperl.so.5.14
#5 0x00007ffff7b1b292 in Perl_sv_free2 () from /usr/lib/libperl.so.5.14
#6 0x00007ffff7b04bc3 in Perl_hv_free_ent () from /usr/lib/libperl.so.5.14
#7 0x00007ffff7b04e6e in ?? () from /usr/lib/libperl.so.5.14
#8 0x00007ffff7b08683 in Perl_hv_undef_flags () from /usr/lib/libperl.so.5.14
#9 0x00007ffff7b1ae66 in Perl_sv_clear () from /usr/lib/libperl.so.5.14
#10 0x00007ffff7b1b292 in Perl_sv_free2 () from /usr/lib/libperl.so.5.14
#11 0x00007ffff7b42cef in Perl_leave_scope () from /usr/lib/libperl.so.5.14
#12 0x00007ffff7b11112 in Perl_pp_leave () from /usr/lib/libperl.so.5.14
#13 0x00007ffff7b0bce6 in Perl_runops_standard () from /usr/lib/libperl.so.5.14
#14 0x00007ffff7aad815 in perl_run () from /usr/lib/libperl.so.5.14
#15 0x0000000000400f89 in main ()
Run Code Online (Sandbox Code Playgroud)
编辑2:Valgrind回溯
这就是我从跑步中得到的valgrind
.虽然我仍然不确定发生了什么,但至少现在我知道应该责怪谁.:-)
==27226== Invalid free() / delete / delete[] / realloc()
==27226== at 0x4C27D4E: free (vg_replace_malloc.c:427)
==27226== by 0xA138F42: PmmREFCNT_dec (in /usr/lib/perl5/auto/XML/LibXML/LibXML.so)
==27226== by 0xA11D3FA: XS_XML__LibXML__Node_DESTROY (in /usr/lib/perl5/auto/XML/LibXML/LibXML.so)
==27226== by 0x4EE770B: Perl_pp_entersub (in /usr/lib/libperl.so.5.14.2)
==27226== by 0x4E7AB90: Perl_call_sv (in /usr/lib/libperl.so.5.14.2)
==27226== by 0x4EEDBD8: Perl_sv_clear (in /usr/lib/libperl.so.5.14.2)
==27226== by 0x4EEE291: Perl_sv_free2 (in /usr/lib/libperl.so.5.14.2)
==27226== by 0x4ED7BC2: Perl_hv_free_ent (in /usr/lib/libperl.so.5.14.2)
==27226== by 0x4ED7E6D: ??? (in /usr/lib/libperl.so.5.14.2)
==27226== by 0x4EDB682: Perl_hv_undef_flags (in /usr/lib/libperl.so.5.14.2)
==27226== by 0x4EEDE65: Perl_sv_clear (in /usr/lib/libperl.so.5.14.2)
==27226== by 0x4EEE291: Perl_sv_free2 (in /usr/lib/libperl.so.5.14.2)
==27226== Address 0x17d0b710 is 0 bytes inside a block of size 32 free'd
==27226== at 0x4C27D4E: free (vg_replace_malloc.c:427)
==27226== by 0xA138F42: PmmREFCNT_dec (in /usr/lib/perl5/auto/XML/LibXML/LibXML.so)
==27226== by 0xA11D3FA: XS_XML__LibXML__Node_DESTROY (in /usr/lib/perl5/auto/XML/LibXML/LibXML.so)
==27226== by 0x4EE770B: Perl_pp_entersub (in /usr/lib/libperl.so.5.14.2)
==27226== by 0x4E7AB90: Perl_call_sv (in /usr/lib/libperl.so.5.14.2)
==27226== by 0x4EEDBD8: Perl_sv_clear (in /usr/lib/libperl.so.5.14.2)
==27226== by 0x4EEE291: Perl_sv_free2 (in /usr/lib/libperl.so.5.14.2)
==27226== by 0x4ED7BC2: Perl_hv_free_ent (in /usr/lib/libperl.so.5.14.2)
==27226== by 0x4EDA919: Perl_hv_common (in /usr/lib/libperl.so.5.14.2)
==27226== by 0x4F0EEC7: Perl_pp_delete (in /usr/lib/libperl.so.5.14.2)
==27226== by 0x4EDECE5: Perl_runops_standard (in /usr/lib/libperl.so.5.14.2)
==27226== by 0x4E80814: perl_run (in /usr/lib/libperl.so.5.14.2)
Run Code Online (Sandbox Code Playgroud)
引用池上的话的评论,因为我无法更好地表达它:
\n\n\n\n\n这是 Perl 或 XS 模块中的错误。当变量的引用计数达到零时,应该释放它,但是当变量的引用计数已经为零时,某些东西试图减少它的引用计数。
\n
正如输出所示valgrind
,在这个特定实例中,问题在于XML::LibXML
。
XML::LibXML
我认为按照Sinan \xc3\x9cn\xc3\xbcr 的建议进行更新,一旦问题被理解并不幸的是,从 2.0001(Debian 稳定版本)更新到 2.0116(CPAN 版本)并没有修复它。
最终解决问题的是修改SetOfThings::explode
以便创建一个新实例并复制它需要的属性,而不是克隆当前实例并删除不需要的属性:
sub explode {\n my $self = shift;\n my $new = __PACKAGE__->new;\n $new->some_attribute(\'whatever\');\n $new->set_of_things( map { $_->explode } $self->constraints );\n return $new;\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n被克隆然后删除的对象的属性之一SetOfThings
是 DOM,它显然XML::LibXML
不升值。得益于这些知识和发布的评论,我终于能够在一个非常小的脚本中重现我的问题并发布错误报告:
#!/usr/bin/perl\n\nuse strict;\nuse warnings;\n\nuse Clone \'clone\';\nuse XML::LibXML;\n\nmy $dom1 = new XML::LibXML::Document;\nmy $dom2 = clone $dom1;\n
Run Code Online (Sandbox Code Playgroud)\n\n正如 ikegami 所指出的,克隆 Perl 变量不会复制库使用的底层 C 结构。但XML::LibXML
确实提供了一种cloneNode
方法,因此将最后一行更改为
my $dom2 = $dom1->cloneNode(1)\n
Run Code Online (Sandbox Code Playgroud)\n\n给出了所需的结果。
\n 归档时间: |
|
查看次数: |
330 次 |
最近记录: |