Re: return in void functions

From: Jeff Schwab (jeffplus_at_comcast.net)
Date: 01/03/04


Date: Sat, 03 Jan 2004 11:42:15 -0500

Martijn Lievaart wrote:
> 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
>

I think we're just not going to agree on this one. I don't care for
your TRACE and LOG macro approach, and I can see that you hate the idea
of giving up the ability to exit a function wherever you see fit. I
congratulate you on having found techniques that work for you, but they
certainly are not appropriate for me. I still recommend avoiding
multiple return points wherever possible, with the exception of... well,
exceptions. :)

-Jeff



Relevant Pages

  • Re: return in void functions
    ... >> easier to use and works with multiple returns and exceptions. ... the ones you want to trace. ... but I don't see what the problem with multiple exit points ...
    (comp.lang.cpp)
  • Re: How to develop a random number generation device
    ... John Larkin writes: ... C doesn't encourage subroutines that have multiple entry and multiple ... Multiple exit points are no problem - you can easily ... Multiple entry points to a *function* are a bit more awkward - but you ...
    (sci.electronics.design)
  • Re: Critical path calculation is incorrect
    ... there are multiple exit points ie. tasks not linked to the Project Finish ... Re. constraints on tasks that make them critical - can you provide ... soon as possible / as late as possible functions) without affecting the ...
    (microsoft.public.project)
  • Re: return in void functions
    ... Tripling the number of exit points per function almost ... >>triples the time it takes to debug a problem. ... > easier to use and works with multiple returns and exceptions. ... > really related to multiple exit points, ...
    (comp.lang.cpp)
  • Re: Debugger Already attached, help
    ... you can quickly see that you can concurrently debug multiple IIS ... if the debugger modules are installed under the framework folder ... How is it MS thinks that only one developer ...
    (microsoft.public.dotnet.framework)