summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDave Mitchell <davem@fdisolutions.com>2003-04-21 14:19:50 +0100
committerRafael Garcia-Suarez <rgarciasuarez@gmail.com>2003-04-23 19:11:01 +0000
commitcccede5366275457276b68bb148b7872098aaf29 (patch)
treedfb369913110eaa12ba8081f848043cf051b63b5
parent1de32f2a8367111f29377c6ed81b538f36717dd9 (diff)
downloadperl-cccede5366275457276b68bb148b7872098aaf29.tar.gz
A new fatal error :
Subject: [PATCH] Perl_croak("Use of freed value in iteration") Message-ID: <20030421121950.GB18189@fdgroup.com> Message-ID: <20030421125433.GC18189@fdgroup.com> p4raw-id: //depot/perl@19316
-rw-r--r--pod/perldiag.pod12
-rw-r--r--pp_hot.c6
-rwxr-xr-xt/cmd/for.t7
3 files changed, 24 insertions, 1 deletions
diff --git a/pod/perldiag.pod b/pod/perldiag.pod
index 92c4d8a40c..3baec3a64c 100644
--- a/pod/perldiag.pod
+++ b/pod/perldiag.pod
@@ -4225,6 +4225,18 @@ defined B<awk> feature. Use an explicit printf() or sprintf() instead.
generally because there's a better way to do it, and also because the
old way has bad side effects.
+=item Use of freed value in iteration (perhaps you modified the iterated array within the loop?)
+
+(F) This is typically caused by code like the following:
+
+ @a = (3,4);
+ @a = () for (1,2,@a);
+
+You are not supposed to modify arrays while they are being iterated over.
+For speed and efficiency reasons, Perl internally does not do full
+reference-counting of iterated items, hence deleting such an item in the
+middle of an iteration causes Perl to see a freed value.
+
=item Use of reference "%s" as array index
(W misc) You tried to use a reference as an array index; this probably
diff --git a/pp_hot.c b/pp_hot.c
index e407b7b477..b74000715e 100644
--- a/pp_hot.c
+++ b/pp_hot.c
@@ -1859,6 +1859,12 @@ PP(pp_iter)
else {
sv = AvARRAY(av)[++cx->blk_loop.iterix];
}
+ if (sv && SvREFCNT(sv) == 0) {
+ *itersvp = Nullsv;
+ Perl_croak(aTHX_
+ "Use of freed value in iteration (perhaps you modified the iterated array within the loop?)");
+ }
+
if (sv)
SvTEMP_off(sv);
else
diff --git a/t/cmd/for.t b/t/cmd/for.t
index 3275c71d2a..3a4bc9b0da 100755
--- a/t/cmd/for.t
+++ b/t/cmd/for.t
@@ -1,6 +1,6 @@
#!./perl
-print "1..12\n";
+print "1..13\n";
for ($i = 0; $i <= 10; $i++) {
$x[$i] = $i;
@@ -71,3 +71,8 @@ for ("-3" .. "0") {
$loop_count++;
}
print $loop_count == 4 ? "ok" : "not ok", " 12\n";
+
+# modifying arrays in loops is a no-no
+@a = (3,4);
+eval { @a = () for (1,2,@a) };
+print $@ =~ /Use of freed value in iteration/ ? "ok" : "not ok", " 13\n";