Re: return in void functions

From: Martijn Lievaart (m_at_remove.this.part.rtij.nl)
Date: 01/03/04


Date: Sat, 03 Jan 2004 17:22:08 +0100

On Sat, 03 Jan 2004 10:23:14 -0500, Jeff Schwab wrote:

>> 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.

No, use one trace class to trace the program flow. When I want to log
variables, I use a different (though related) class.
 
> 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 )
> {
        TRACE(sort_two_objects);

> 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.

 see below

>
> if( already_sorted )
> {
> return;
> }
>
> // A Trace object defined here will not be destructed if the
> return // statement is used.
>
> T copy_of_a = a;

        LOG("copy_of_a=" << a);

>
> a = b;
> b = copy_of_a;
> }

Why do it any other way? Yes multiple exit points can make ad-hoc
cerr-debugging harder, but one should not do that anyhow. Writing the
TRACE and LOG macros is pretty trivial and make life much easier.

>> 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.

That is true, but I don't see what the problem with multiple exit points
is if you're going to rerun the program under the debugger anyhow.

The only real advantage I can see of avoiding multiple exitpoints is that
one can put a breakpoint on the common exit. In practice, I don't miss it.

>> 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."

I'm not talking about complete programs being stories, I'm talking about
pieces of code, most probably a function. If you do that, the complete
program is easy to read and debugging gets much easier. So your argument
about binary search is not relevant, that is how one should always debug.

If the program is hard to read, it is hard to debug. If multiple exit
points make a function harder to read, they are misused. I still don't see
why multiple exit points would be a problem here.

M4



Relevant Pages

  • Re: JSH: Without a trace
    ... given a multiple of a polynomial it has been well ... > and it is true that you can divide 5 from that factorizaton giving ... > without leaving a trace. ... > In my case I have precedent from thousands of years of mathematics ...
    (sci.math)
  • Re: return in void functions
    ... Yes multiple exit points can make ad-hoc ... Exceptions carry information back up the call stack ... debug time is significantly reduced. ...
    (comp.lang.cpp)
  • JSH: Without a trace
    ... given a multiple of a polynomial it has been well ... and it is true that you can divide 5 from that factorizaton giving ... without leaving a trace. ... In my case I have precedent from thousands of years of mathematics ...
    (sci.math)
  • Re: [patch 4/5] x86, ftrace, hw-branch-tracer: reset trace on close
    ... the trace, the trace is not contiguous, anyway. ... So you want multiple reads of /debug/tracing/trace to return different ... If you use quilt, you can add: ... VAT Registration No.: DE129385895 ...
    (Linux-Kernel)
  • Contacts dissapearing
    ... multiple versions of Outlook. ... patialy dissapearing without a trace. ... party software being used to share certain folders ... but the problem effects any contact list including the ...
    (microsoft.public.outlook.contacts)