【问题标题】:Where is the memory leak in my Perl XS code?我的 Perl XS 代码中的内存泄漏在哪里?
【发布时间】:2021-01-13 00:21:51
【问题描述】:

我有一个用 C++ 编写并使用 Inline::CPP 从 Perl 执行的大型程序。该代码似乎使用了大量内存,所以我假设存在某种泄漏。我编写了以下代码来重现相同的问题,但要简单得多。当我循环代码 1,000,000 次以测试代码的性能时,我发现了泄漏。这个简单的 Perl 脚本使用 828MiB,而我的完整程序使用 1.3GiB。

我已经尝试了很多东西,比如在代码中的各种变量上使用SvREFCNT_decnewRV_noincsv_freesv_2mortal,但我无法降低内存使用量。

这是我的示例代码:

use Data::Dumper;

print Dumper test ();

use Inline 'CPP' => << 'CPP';
    #include <array>

    using namespace std;

    AV *array_to_av (const array<int,3> &v)
    {
        AV *array = newAV ();

        for (int i : v) {
            av_push (array, newSViv (i));
        }

        return array;
    }

    SV *test_leak ()
    {
        HV *hash = newHV ();

        AV *array1 = array_to_av ({1,2,3});
        AV *array2 = array_to_av ({1,2,3});
        AV *array3 = array_to_av ({1,2,3});

        SV *value1 = newRV_noinc ((SV *)(array1));
        SV *value2 = newRV_noinc ((SV *)(array2));
        SV *value3 = newRV_noinc ((SV *)(array3));

        hv_stores (hash, "Test1", value1);
        hv_stores (hash, "Test2", value2);
        hv_stores (hash, "Test3", value3);

        return newRV_noinc ((SV *)(hash));
    }

    SV *test ()
    {
        SV *hash;

        for (int i = 0; i < 1000000; i++) {
            hash = test_leak ();
        }

        return hash;
    }
CPP

sleep 10;

【问题讨论】:

  • 我不擅长 xs,但在我编写的类似代码中,sv_2mortal((SV*)flist);AV* flist = newAV(); 之后(然后数组 flist 被填充等)。这是针对 C 而不是 C++。
  • @zdim 在AV *array = newAV (); 之后放置sv_2mortal ((SV*)array); 并没有改变内存使用情况,它只会导致类似“尝试释放未引用的标量:SV 0x55748d5a6c68,Perl 解释器:0x557458d6b2a0 at testleak.pl 行54." XS 代码是 C,你可以用 C++ 编写标准 C,所以我认为是否使用 C++ 并不重要。我也尝试删除所有 C++ 功能并改用 Inline::C,但问题仍然存在。
  • 嘿...我希望这会有所帮助,因为我看不到显示的代码中的什么可以释放内存。 (但现在我也发现我误读了 array_to_av() 的用途)。

标签: c++ perl xs inline-c


【解决方案1】:

您需要释放在for 循环中未返回到 Perl 脚本的哈希值。这个循环:

for (int i = 0; i < 1000000; i++) {
    hash = test_leak ();
}

应该是这样的:

for (int i = 0; i < 1000000; i++) {
    hash = test_leak ();
    SvREFCNT_dec(hash);  // Free the memory not returned to Perl
 }
 hash = test_leak();  // The final hashref is returned to Perl

【讨论】:

    猜你喜欢
    • 2013-08-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-04-02
    • 2011-10-28
    • 2011-09-10
    • 1970-01-01
    相关资源
    最近更新 更多