【问题标题】:Enumerating all references in a perl interpreter枚举 perl 解释器中的所有引用
【发布时间】:2013-06-19 03:26:23
【问题描述】:

手头的问题是发现内存泄漏。我使用了 Devel::Refcount 来显示我的应用程序中的哪些对象不应该保留在内存中。

已经提出了三种方法来找到这些结构的难以捉摸的链接。

1 - 可能存在一种数据结构,可以让我获取引用我的对象的符号列表,这将是理想且直接的。

2 - 迭代所有已定义命名空间中的符号表以查找引用并使用迭代堆栈来确定它在哪里。

3 - 插入一个钩子,让我可以在特定引用的链接计数向上或向下更改时记录堆栈位置以及持有该链接的符号的地址。我可以使用它来查找哪些符号直接持有我的引用。

那么这可能吗?这种自省是很棘手的事情,我可能对 perl 非常了解,但我不知道该怎么做。我对padwalker的研究似乎可能有钥匙,但没有取得成果。你的想法?

【问题讨论】:

  • 请注意,您可以使用内置的Internals::SvREFCNT(%$self)访问引用计数
  • 我有引用计数。我想要那些持有非零引用计数的结构的命名空间定义,以及持有非零引用计数的结构等,直到我在不应该的范围内找到具有定义值的变量。
  • 我相信你有最终的 refcnt。既然你知道哪个对象在泄漏,你可以使用这个函数和标准调试来定位泄漏。

标签: perl memory-leaks introspection


【解决方案1】:

您可以尝试遍历 :: 哈希;那就是主命名空间,它将符号名称映射到值。该命名空间中以 :: 结尾的任何键都是命名空间,可以通过迭代从命名空间获得的值来迭代,或者只是将该命名空间视为哈希;即

>perl -le 'print foreach keys %::'
version::
/
stderr
_<mro.c
Tie::
utf8::
"
re::
CORE::
DynaLoader::
mro::
stdout
attributes::

stdin
ARGV
INC
ENV
Regexp::
UNIVERSAL::
$
_<perlio.c
main::
_<perlmain.c
PerlIO::
0
_<universal.c

@
_<xsutils.c
STDOUT
IO::

_
STDERR
Internals::
STDIN
DB::





   >perl -le 'print foreach keys %mro::'
    get_mro
    get_linear_isa
    get_pkg_gen
    set_mro
    invalidate_all_method_caches
    is_universal
    method_changed_in
    get_isarev

【讨论】:

  • 这只会列出包变量。大多数变量不是包变量。
  • 这将在任何命名空间中找到任何变量;无论是全局变量还是包变量。词法变量不在命名空间中,所以我回答的部分问题不适用于那里。
  • (“无论是全局变量还是包变量”没有意义。每个包变量都是全局的,每个全局都是包变量。)准确地说,词法和匿名变量都不会被发现,他们可以很好地保存对对象的引用。事实上,几乎可以肯定会成为其中之一。您的回答没有帮助,而且可能会导致问题得不到应有的重视。
【解决方案2】:

Test::LeakTrace怎么样?

#!perl
use Test::LeakTrace;

no_leaks_ok {
    # Suspect code here
};

这会多次运行该块,然后如果解释器中的所有 Perl 值都增加,则 Test::LeakTrace 认为存在内存泄漏。

【讨论】:

  • 不幸的是,这似乎告诉我分配发生在哪里(我已经通过应用程序上下文知道)我想知道谁对先前创建的引用具有非弱引用。
猜你喜欢
  • 1970-01-01
  • 2015-09-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-06-13
  • 1970-01-01
相关资源
最近更新 更多