我有一个Perl Tk GUI应用程序,有时会在超过4GB的RAM使用量后崩溃。使用Perl Tk,在某些情况下,我可以超过4GB的RAM使用量,并且在控制台应用程序中运行测试时,我没有超过4GB的问题。
- 操作系统:Microsoft Windows [Version 10.0.19044.2006]
- Perl版本:v5.30.3
- Tk版本:804.036(CPAN上最新可用版本)
Perl几乎每次崩溃都会输出此错误,但是有时候它会崩溃而没有错误:
Free to wrong pool 678ea0 not e228dd0 at .\common\GUI_TESTS\test_memory_hog_gui.pl line 41.
搜索此错误时,我发现所有结果都与多线程有关,而我们的应用程序不使用多线程。
我认为这可能是因为我们将某些内容配置为32位而不是64位,因此我按照此问题中的说明进行了操作,并发现一切都已配置为64位。
perl -V:ivsize # ivsize='8';
perl -V:ptrsize # ptrsize='8';
perl -V:archname # archname='MSWin32-x64-multi-thread';
下面是一个示例GUI应用程序,当内存超过4GB时崩溃。我从我们的应用程序中精简出来,并且崩溃的行为是相同的。我们使用的数据结构显然要大得多,因此我将我们的简化版本克隆多次以通过4GB阈值。
use strict;
use warnings;
use Tk;
use Tk::LabFrame;
use Clone;
my $MAIN_WINDOW = MainWindow->new;
$MAIN_WINDOW->minsize(400, 400);
my @dataStructureClones = ();
my $textBox;
my $button_frame = $MAIN_WINDOW->LabFrame(-label => "Test", -relief => 'groove', -borderwidth => 2)->pack();
$button_frame->Button(
-text => 'Run Crashing Operation',
-command => sub {
my $dataStructureThatCrashes = {
NETLIST_INFO => {
EXTRA_PROPERTIES => {
C_SIGNAL => {},
NET => {},
},
NET_LIST => [
# omitting this call will allow the program to exceed 4GB until after it finishes the loop
{ NL_INDEX => 0, }
]
},
};
my $lastUpdate = time();
push @dataStructureClones, $dataStructureThatCrashes;
for (1 .. 5000000) {
if (time() - $lastUpdate > 1) {
# omitting this call will allow the program to exceed 4GB
$textBox->insert("end", "Cloning hash ($_)...\n");
$MAIN_WINDOW->update();
$lastUpdate = time();
}
push @dataStructureClones, Clone::clone($dataStructureThatCrashes);
}
}
)->grid(-row => 0, -column => 0);
$textBox = $MAIN_WINDOW->Scrolled(
'Text',
-relief => 'groove',
-background => 'light grey',
-foreground => 'black',
-wrap => 'char',
-scrollbars => 'osoe',
-width => 110,
-height => 24,
)->pack(-side => 'top', -fill => 'both', -expand => 1);
MainLoop;
注意事项:
- 将第28行注释掉可以使程序正常运行。
- 将第38行注释掉会使克隆循环完成执行,但在克隆结束大约15秒后会出现类似错误导致程序崩溃。
类似的错误:
Free to wrong pool 1008ea0 not fcedf7a8 at C:/Strawberry/perl/site/lib/Tk.pm line 424.
我在我们拥有的Linux虚拟机(CentOS 7)上尝试过这个程序,问题没有发生。
perl
+perltk
无法复现该 bug。因此问题可能是由于 windows 上的perl
/perltk
引起的。我不知道perl
如何工作,但是perltk
是否可能是32位的,即使perl
本身是64位的?我认为这可能会导致相同的问题。 - TheLizzard