Subject: | [PATCH] Fix memory leak in natatime() |
natatime() has a bug which prevents it from ever freeing the values it returns. The attached
patch fixes the bug, and includes a test which (if you have Test::LeakTrace installed) ensures
that no memory is leaked. (If you don't have Test::LeakTrace installed, the memory-leak test is
quietly skipped.)
It should be straightforward to apply the same leak-testing approach to any other functions;
since memory leaks in some functions have been a long-standing problem with List::MoreUtils,
this seems valuable to me.
Subject: | natatime_leak.diff |
From 13ba5f11a35cdbd4094d6f2e117caebb171f6607 Mon Sep 17 00:00:00 2001
From: Aaron Crane <arc@aaroncrane.co.uk>
Date: Tue, 8 Mar 2011 15:07:15 +0000
Subject: Fix memory leak in natatime()
---
MoreUtils.xs | 3 +--
t/lib/Test.pm | 20 +++++++++++++++++++-
2 files changed, 20 insertions(+), 3 deletions(-)
diff --git a/MoreUtils.xs b/MoreUtils.xs
index d091bf9..14d72f2 100644
--- a/MoreUtils.xs
+++ b/MoreUtils.xs
@@ -1089,9 +1089,8 @@ _natatime_iterator ()
EXTEND(SP, nret);
for (i = 0; i < args->natatime; i++) {
- if (args->nsvs) {
+ if (args->curidx < args->nsvs) {
ST(i) = sv_2mortal(newSVsv(args->svs[args->curidx++]));
- args->nsvs--;
}
else {
XSRETURN(i);
diff --git a/t/lib/Test.pm b/t/lib/Test.pm
index 3d001f6..08f6be8 100644
--- a/t/lib/Test.pm
+++ b/t/lib/Test.pm
@@ -7,7 +7,7 @@ use List::MoreUtils ':all';
# Run all tests
sub run {
- plan tests => 154;
+ plan tests => 155;
test_any();
test_all();
@@ -444,6 +444,14 @@ sub test_natatime {
push @r, @vals;
}
is( arrayeq( \@r, \@a ), 1, "natatime2" );
+
+ leak_free_ok('natatime leaks no memory', sub {
+ my @y = 1;
+ my $it = natatime 2, @y;
+ while ( my @vals = $it->() ) {
+ # do nothing
+ }
+ });
}
sub test_zip {
@@ -654,4 +662,14 @@ sub arrayeq {
return 1;
}
+sub leak_free_ok {
+ my $desc = shift;
+ my $code = shift;
+ SKIP: {
+ skip 'Test::LeakTrace not installed', 1
+ unless eval { require Test::LeakTrace; 1 };
+ &Test::LeakTrace::no_leaks_ok($code, $desc);
+ }
+}
+
1;
--
1.7.3.5