Re: various exits from function with one general clean-up?

From: Herbert Rosenau (os2guy_at_pc-rosenau.de)
Date: 12/06/04


Date: Mon, 6 Dec 2004 21:45:31 +0000 (UTC)

On Mon, 6 Dec 2004 15:26:04 UTC, Felix Kater <f.kater2@gmx.net> wrote:

> Hi,
>
> when I need to execute a general clean-up procedure (inside of a
> function) just before the function returns -- how do I do that when
> there are several returns spread over the whole function?

There are different details:
- follow the roule that no fuction should be have more lines
  of code than a screen (print) page can show.
  This makes it easier to understund the code
  and helps debugging the whole program
- if the function goes too big for the rule above you tries
  to make too much details at once. Then break down the whole
  job in multiple little functions (even as each function
  gets called only one).
- define the style for each function:
  - has only ONE return in case its job gets done well
    but multiple returns on errors.
    This will be the case when the awaited result is:
       "done anything well"
  - has only one return in case its job fails
    but multiple returns its job is done well.
    This will be the case when the natural result of that job
    is: "something fails as expected"
  - has only exactly ONE return point
    This is the case when even something fails the total
    work has to be done and either NO fail at all occurs
    or even NO result is needed.
  depending if you can identify WELL as ONE single value
  or its easier to define ONE single value as error indicator.
- define the most significant value as return value and
  less significant ones (when there are some)
  as parameter.
  The function result will be
  - only an indicator of success/fail (like pointer/NULL pointer)
    optionally another parameter gives more details about errors
  - a pure error code
    - one value indicates success (e.g. 0)
      any other gives the error number
  In both cases you needs on the calling point only one if
  to differ between success and fail of this step
- Splitting out a whole switch statement
  into a separate function using the roles above.
  This helps you to differ WHAT from HOW.
- You may even have a need to split out each (or some)
  case into own functions to separate out "WHAT is to do"
  from "HOW is it done"
- in general:
  when a function gets too big to follow the first role
  it is easy too see that you have too much work for a
  single function.
  Spitting out "WHAT" from "HOW" is to do helps you
  to get your mind clean. Define a function for each "What"
  to hide details from the "WHAT".
  If "HOW" is too much again split this detail again.
  This method will allow you
  - debug each detail alone by writing a debug main(),
    compile little function alone, test it using different
    testdata.
  - debug outer functions using theyr input leaving out
    inner functions during trace because you knows they
    should work already.
- split up each function in at least 3 logical blocks
  whereas each can be empty:
  1. init
     A check input parameters when needed
     B allocate resources the fuction and its helper functions
       needs - but only if A was successfull
       a memory/files needed for internal work
       b memory/files needed to return to caller
  2. do the work only when 1. successfull
  3. clean up
     free all resources you have not return to the caller,
     a close/remove files (only when they are created/opened
       successfull).
       Attention: the result from close() and rmove()
          may change your result from success to fail!
     b free memory (free() allows to be called with NULL
       pointers! So you can blindly free() anything.
  Each of 1-3, A+B, a+b can be done one or more helper fuctions.
  if, if - else, if - else - if is a wounderful constunct - but
  only if you gets your code so structured that they are NOT
  got nested deep. Deep nesting points you to a design error.
  Roll up the WHAT/HOW levels from scratch at this point.

At least your whole program will follow the rule:
I WHAT is to do.
     Describes a (sub)job on what kind on work is to do
     but lefts open HOW it gets done by calling II as function
     for each step. When the WHAT is too complex the (sub)job
     gets broken into a bit more detail of functions I.
     This will describe your program in a logical way
     without holding up with detail questions.
II HOW is it done
     This does the real work in detail. In general you would
     go recursively to I to get more description of WHAT
     by working out mathematical formulas, formatting data
     and so on. You'll break down to I again when during design
     you sees more need to describe WHAT is to do and recursive
     into II when the HOW is too complex to get done in a single
     page.

So evakuating the body of nested or long wounded loops (for, while,
do) into functions of theyr own will remove lots of details from your
brain until you writes the details. You shortens switch statements to
"some different work based on this" is done. You shortens if and else
to "when this condition then this kind of work is to do" without
showing the details until you writes them.

This helps you to avoid lots of
- nested if and else if statements
- gotos (destroying the flow)
- higher nested for/while/do statements
in hiding details fom the flow until you needs them really.

I'm learned that techics in times whereas
- memory was only in amout of KB instead MB available
- assembly was the highest possible programming language
by
- thinking in objects builded of objects builded....
  but nothing on help available than my brain to build them
  (is there another method to get hudge programms in low memory?)
- need of reuse so many functions as possible
  because having every time to less memory available
- having real time work on CPUs having not even 1 single MHz (instead
of xxGHz today).

-- 
Tschau/Bye
Herbert
Visit http://www.ecomstation.de the home of german eComStation
eComStation 1.2 Deutsch ist da!


Relevant Pages

  • Re: xmalloc string functions
    ... of mallocwhen you are trying to allocate a structure ... caller that fact like I do when mallocfails to delever me the ... amount of memory I ask it for. ... exit() does NOT write buffers not already given into the stream, ...
    (comp.lang.c)
  • Re: thanks and question
    ... Warcraft, I get random crashes, my specs are: ... about it now, becuase im still on Safe Fail Defualts lol, Video Card, ... I *still* tend to suspect memory problems. ... Then, if it fails with one stick and not the other, you have your ...
    (alt.comp.hardware.pc-homebuilt)
  • Re: thanks and question
    ... about it now, becuase im still on Safe Fail Defualts lol, Video Card, ... Ran memtest and everything 2 times, checked hard drive, CPU Mobo, case ... I *still* tend to suspect memory problems. ... Then, if it fails with one stick and not the other, you have your ...
    (alt.comp.hardware.pc-homebuilt)
  • Re: Is there no compression support for large sized strings in Python?
    ... > pylzma fails to decompress running endlessly consuming 99% of CPU time ... Is there no compression support for large sized strings in Python? ... you're probably measuring windows' memory managment rather than the com- ... pression libraries themselves (Python delegates all memory allocations>256 bytes ...
    (comp.lang.python)
  • Re: msync(2) bug(?), returns AOP_WRITEPAGE_ACTIVATE to userland
    ... memory-pressure conditions. ... int err = -EIO; ... under memory pressure conditions could lead to a deadlock. ... redirty our page and return "success" so that the VM will call us ...
    (Linux-Kernel)