Re: Which scope for variables being used in a loop?
From: Esmond Pitt <esmond.p...@nospam.bigpond.com>
The effect as written is that the *last* 3 objects allocated
can't be GC'd until the scope they are declared in exist.
Yes, I agree. In a cases where one of those last 3 objects might be
really big, assuming the programmer can anticipate that as a
likelihood, it would seem prudent to explictly null out the
relevant local pointers just before reaching the bottom of the
inside of the loop. That wouldn't cause any practical difference
for any but the last 3, because each group of 3 pointers (except
the last group) immediately gets overwritten by the next group of 3
when the loop repeats, but it'd protect the last three from being
held too long. I'm assuming what somebody else said, that in fact
the stack frame is created upon entry to the method, to hold the
longest chain of local variables in the whole block, so even though
the variables declared in the inner loop-block go out of scope they
are still unavailable to be garbage collected until the whole
method returns.
And I agree that the variables should be declared within the inner
loop-block, rather than out in the main body of the method, for
several reasons (defense against accidently re-using a value later
in the same method, and allowing local allocations in one loop to
overlay local allocations in another loop. Hence you can't null-out
the three pointers just once after the loop exits, because the
variables are out of scope already, still held by the GC yet
untouchable by the programmer! (Hey, maybe loops should allow a
"finally" clause which performs actions after the very last time
through the loop but before local variables go out of scope?? Nah,
too ugly. How about a "finally" or "volatile" clause on the local
declaration itself, such that the pointer-value of the variable is
forcibly nulled-out at the moment just before the variable goes out
of scope the last time through the loop? Nah, impractical. How
about a "volatile" declaration for the entire *loop* (not the block
inside the loop), such that all stack values allocated by any block
within that loop are nulled out upon exit from the loop? I think
that would be logically consistent, clean, and doable.)
I favour declaring all variables in the innermost scope possible,
I agree completely.
But note such a programming style precludes this loop-search pattern:
for (int ix=0; ix<=max && obj.elementAt(ix)!=target; ix++) {}
if (ix>max) then return(<didn'tfindvalue>);
else return(<foundvalue>);
because the post-loop test can't work because ix is already out of scope.
But I always preferred this style anyway:
for (int ix=0; ; ix++) {
if (ix>max) return(<didn'tfindvalue>);
if (obj.elementAt(ix)==target) return(<foundvalue(ix)>);
}
And who would really prefer this half-of-each pattern?
for (int ix=0; ix<=max; ix++) {
if (obj.elementAt(ix)==target) return(<foundvalue(ix)>);
}
return(<didn'tfindvalue>);
What I don't like about that is that one return is after the loop,
whereby maintainers might not notice the *other* return from inside
the loop.
And I never liked this pattern either:
bool success=false; int savedix;
for (int ix=0; ix<=max; ix++) {
if (obj.elementAt(ix)==target) {
success=true; savedix=ix; break;
}
}
if success then return(<foundvalue(savedix)>)
else return(didn'tfindvalue>);
Although I did find myself forced to invent that last horrible
pattern very long ago in another language that is overly (IMO)
restrictive about where you can do what. No, it wasn't pascal.