Re: return in void functions
From: Jeff Schwab (jeffplus_at_comcast.net)
Date: 01/03/04
- Next message: Jeff Schwab: "Re: vector, list and deque"
- Previous message: Christof Krueger: "Re: Nonlocal Store (global and class static variables)"
- In reply to: Martijn Lievaart: "Re: return in void functions"
- Next in thread: Martijn Lievaart: "Re: return in void functions"
- Reply: Martijn Lievaart: "Re: return in void functions"
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]
Date: Sat, 03 Jan 2004 10:23:14 -0500
Martijn Lievaart wrote:
> On Fri, 02 Jan 2004 15:30:43 -0500, Jeff Schwab wrote:
>
>
>>Why yes, Omniscient One! The design problem was the use of blocks of
>>code having multiple exit points. Most of my typical debug cycle is
>>spent putting "cerr" lines (or gdb break points) at strategic places in
>>the code. Tripling the number of exit points per function almost
>>triples the time it takes to debug a problem.
>>
>>When I throw an exception in a non-trivial program, I include the file
>>name and line number as part of the exception, so I know exactly where I
>>need to start looking when an exception is thrown. Trying to track an
>>issue back to root cause is far more difficult in spaghetti code than in
>>code that avoids mid-block return statements. This should not be news
>>to you.
>
>
> You'll have a hard time tracing exceptions with this design. Why not
> define a trace object, that prints in constructor and destructor? Much
> easier to use and works with multiple returns and exceptions. It's what I
> do if I need this.
So, each time you want to debug a function with multiple return points,
you must:
1) Define a class with member references to all of the function's local
variables; at least, the ones you want to trace.
2) Find a cozy place somewhere before any of the function's return
points, but after all the traced variables have been defined. IME, this
is often impossible. Here is a simplistic case that reflects the common
practice of defining some variable, returning if a check succeeds, and
otherwise defining some other variables:
template< typename T >
void sort_two_objects( T a, T b )
{
bool already_sorted = a < b;
// A Trace object defined here cannot trace the value of copy_of_a,
// even if the return statement is not used.
if( already_sorted )
{
return;
}
// A Trace object defined here will not be destructed if the return
// statement is used.
T copy_of_a = a;
a = b;
b = copy_of_a;
}
> I never was a fan of not allowing multiple exit points, but exceptions
> embedded it in the language, so I guess we better get used to it. I know I
> don't have any problem with it.
Exceptions do provide "extra" exit points, but they are not the same as
return statements. Exceptions carry information back up the call stack
about what went wrong, and why. Often, the information obtained in a
high-level catch block is sufficient, and there is no need to look at
the lower-level code at all. Even when there is such a need, since my
exceptions always include the line number and file number of the
corresponding throw statement, I know exactly which exit point to watch.
> Obviously, multiple exit points, like any language feature can be used
> and mis-used. I concur that they can introduce problems, but only if
> mis-used. My personal guideline in this is that the code should read like
> a story. If not, you have a maintenance problem at least. So this is not
> really related to multiple exit points, but to obfuscated coding.
I've heard that theory before. The fact is that programs are not
stories. When I'm debugging a large piece of code, I have no desire to
start at the beginning and proceed to the point of the problem. The
time required for such an approcach is linear with the number of lines
leading to the point of the problem. By doing instead a binary search
for the problem, debug time is significantly reduced. This approach is
eased greatly by the absence of spurious return statements. Any extra
return statement is what I would call "obfuscated code."
-Jeff
>
> M4
>
- Next message: Jeff Schwab: "Re: vector, list and deque"
- Previous message: Christof Krueger: "Re: Nonlocal Store (global and class static variables)"
- In reply to: Martijn Lievaart: "Re: return in void functions"
- Next in thread: Martijn Lievaart: "Re: return in void functions"
- Reply: Martijn Lievaart: "Re: return in void functions"
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]
Relevant Pages
|