Perl Tk 应用程序有时会在内存使用量超过 4GB 后崩溃

Eri*_*tig 15 memory windows perl tk-toolkit perltk

我有一个Perl Tk GUI应用程序,有时在 RAM 使用量超过 4GB 后会崩溃。在某些情况下,使用 Perl Tk,我的 RAM 使用量可以超过 4GB,并且在控制台应用程序中运行测试时,我没有遇到超过 4GB 的问题。

  • 操作系统:Microsoft Windows [版本 10.0.19044.2006]
  • Perl版本:v5.30.3
  • Tk 版本:804.036(CPAN 上最新可用)

Perl几乎每次崩溃时都会吐出这个错误,但 有时它会崩溃而没有错误:

释放到错误的池 678ea0 而不是 e228dd0 位于 .\common\GUI_TESTS\test_memory_hog_gui.pl 第 41 行。

在搜索此错误时,我能找到的所有内容都与多线程相关,而我们的应用程序不使用多线程

我想这可能是因为我们有一些配置为 32 位而不是 64 位,所以我按照这个问题中的说明进行操作,发现所有内容都配置为 64 位

perl -V:ivsize          # ivsize='8';
perl -V:ptrsize         # ptrsize='8';
perl -V:archname        # archname='MSWin32-x64-multi-thread';
Run Code Online (Sandbox Code Playgroud)

下面是一个 GUI 应用程序示例,该应用程序在内存超过 4GB 后崩溃。我已经从我们的应用程序中总结了这一点,崩溃行为是相同的。我们使用的数据结构显然要大得多,因此我多次克隆我们的简化版本以通过 4GB 阈值。

perl -V:ivsize          # ivsize='8';
perl -V:ptrsize         # ptrsize='8';
perl -V:archname        # archname='MSWin32-x64-multi-thread';
Run Code Online (Sandbox Code Playgroud)

注意事项:

  1. 注释掉第28行可以使程序正常运行
  2. 注释掉第 38 行会使克隆循环完成执行,但在克隆完成后大约 15 秒,它会崩溃并出现类似的错误。

类似的错误:

免费到错误的池 1008ea0 而不是 fcedf7a8,位于 C:/Strawberry/perl/site/lib/Tk.pm 第 424 行。

我在我们拥有的 Linux 虚拟机 (CentOS 7) 上尝试了此操作,但问题并未发生。

Don*_*ows 3

第一个问题是底层 Tk 库具有内部内存分配器,只能处理最多大约 2GB 的内存分配(由于很久以前的 ABI 错误强制内存对象大小参数为int; 修复这一点很混乱并且破坏了很多东西)。内部数据结构意味着,当你超过 2GB 时,你不一定会把东西炸毁,但你是在玩火,或者也许用硝化甘油来比喻会更好。

第二个问题,您本身尚未遇到但很快就会遇到,是 4GB 的文本数据对于在 GUI 中实际使用来说太大了!一次获得所有详细信息简直让用户不知所措。

我只能在这里概述解决方案,即利用这样一个事实:这么多数据永远不会同时显示在屏幕上。相反,您将需要滚动数据......但您可以连接滚动机制来滚动数据本身的窗口,而不是将小部件的视图移动到数据中。当发生滚动事件时,您可以删除窗口的内容并从基础数据源中替换它。(这只是一个大纲,因为我不知道如何在 Perl/Tk 中执行此操作...并且甚至必须查找 Tcl/Tk 的详细信息,尽管我对此了解得更好。)我读过有关人们做的事情这可以可视化来自数据库查询的非常大的结果集,并怀疑类似的东西对您有用。

当然,如果您将所有数据放入数据库中(为了获得筛选支持),那么您可能会找到更好的查询和更新方法,而无需一次查看大量数据......