473,396 Members | 2,018 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,396 software developers and data experts.

various exits from function with one general clean-up?

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?

My first approach: Use "while(1)" and "break", however this doesn't work
if there is another loop inside (since I can't break two loops at the
same time):

void f(){
while(1){

if ...

break; /* first return: */

switch(...){
case ...:

break; /* second return (doesn't work): */
}

/* other code */

break; /* break in any case */
}
/* clean up procedure */
}
Could someone solve this -- or maybe provide a better solution in
general?

Thanks
Felix
Nov 14 '05 #1
7 2213

"Felix Kater" <f.******@gmx.net> wrote in message
news:20*********************@comppasch.pi4.lan...
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?
Then don't do that...
Could someone solve this -- or maybe provide a better solution in
general?
Hint A) Use a 'goto'. This is one of the *very* few occasions where I would
advice this.
Hint B) Keep a 'status' local var and check it for every step, return status
*once*.
Hint C) Abstract 'cleanup' into a specialized function. Call it when
appropriate.

Thanks
Felix

Nov 14 '05 #2
In article <20*********************@comppasch.pi4.lan>,
Felix Kater <f.******@gmx.net> wrote:
My first approach: Use "while(1)" and "break"


The result would be completely unreadable even if it worked. Use a
straightforward goto instead.

-- Richard
Nov 14 '05 #3
On Mon, 6 Dec 2004 16:26:04 +0100, Felix Kater
<f.******@gmx.net> wrote:
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?
I assume that you mean cleaning up mess local to the function, rather
than global mess (the latter is best done with another function called
on exit).
My first approach: Use "while(1)" and "break", however this doesn't work
if there is another loop inside (since I can't break two loops at the
same time):
No, it doesn't. "Labelled break" would be useful.
Could someone solve this -- or maybe provide a better solution in
general?


One way is to restructure the code so that there is only one exit, using
if/else etc. and storing the result for the exit. Another (which can be
combined) is to use status flags and/or state variables.

Or you can use goto, which is in many cases the cleanest solution
especially for error traps. If a function has one label at the bottom,
clearly marked and commented, and the only thing it does is cleanup and
exit, it can be easily understood and maintained (better than
duplicating code for each return or having a baroque system of flags).

Chris C
Nov 14 '05 #4
Chris Croughton wrote:
[...]
One way is to restructure the code so that there is only one exit, using
if/else etc. and storing the result for the exit. Another (which can be
combined) is to use status flags and/or state variables.


Another way to do the restructuring is to wrap the multi-
return function inside a caller that handles the resource
allocation and cleanup:

void f(void) {
char *string = malloc(...);
FILE *stream = fopen(...);
inner_f_with_multiple_returns(string, stream);
fclose(stream);
free(string);
}

This requires that the "dirtying" can all be done before
the "real work," and that all the cleanup can be postponed
until afterward. However, that pattern describes quite a
few functions -- and those that it doesn't describe might
be candidates for decomposition anyhow.

--
Er*********@sun.com

Nov 14 '05 #5
On Mon, 06 Dec 2004 12:34:09 -0500, Eric Sosman
<er*********@sun.com> wrote:
Chris Croughton wrote:
[...]
One way is to restructure the code so that there is only one exit, using
if/else etc. and storing the result for the exit. Another (which can be
combined) is to use status flags and/or state variables.
Another way to do the restructuring is to wrap the multi-
return function inside a caller that handles the resource
allocation and cleanup:


Yes, if the resources are simple enough that's the way I do it. If it
involves passing more than a couple of extra parameters then I find it
messy (or if some of the allocation needs extra calculation first).
This requires that the "dirtying" can all be done before
the "real work," and that all the cleanup can be postponed
until afterward. However, that pattern describes quite a
few functions -- and those that it doesn't describe might
be candidates for decomposition anyhow.


As in the woman who asked "Is Beethoven still composing?" and got the
reply "No madam, he is decomposing!" <g>. I think some code should
definitely decomposed, or even composted...

Yes, most functions I've used which allocate and then free resources
have been able to be implemented using wrappers as you describe. A few
haven't, and some have been imossible to split up without making the
interfaces very odd and nonintuitive...

(Actually, I haven't used a goto in C for at least 10 years, I've always
been able to code round it. I've seen some code where it was the
"obviously correct" answer, though...)

Chris C
Nov 14 '05 #6
On Mon, 6 Dec 2004 15:26:04 UTC, Felix Kater <f.******@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!
Nov 14 '05 #7
In article <20*********************@comppasch.pi4.lan>,
Felix Kater <f.******@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?
This points to one of the deficits in standard c.
I leave it to others to point to a way out, personally I
would probably use goto here.

The theoretical nice way to do this is, is coroutines, where
a facility and its clean ups can be tied together.
Nobody realizes this nowadays, 'cause when all you have is a hammer...
(I can't elaborate here, without going of topic.)
Thanks
Felix


Groetjes Albert.

--

--
Albert van der Horst,Oranjestr 8,3511 RA UTRECHT,THE NETHERLANDS
One man-hour to invent,
One man-week to implement,
One lawyer-year to patent.
Nov 14 '05 #8

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

14
by: Klaus Neuner | last post by:
Hello, I need to gather information that is contained in various files. Like so: file1: ===================== foo : 1 2 bar : 2 4
0
by: David C. allen | last post by:
I am calling a webclass using the proxy functions generated when I referenced the webclass. When I call the end function for the EndGetBug function the function exits without error on the Dim...
15
by: Walter Dnes (delete the 'z' to get my real address | last post by:
A long time ago, in a place far away, there was an OS called DOS that had standard numeric return codes. Regardless of the programming language used, the same error return codes were supposed to...
29
by: keredil | last post by:
Hi, Will the memory allocated by malloc get released when program exits? I guess it will since when the program exits, the OS will free all the memory (global, stack, heap) used by this...
14
by: Mr Newbie | last post by:
I am often in the situation where I want to act on the result of a function, but a simple boolean is not enough. For example, I may have a function called isAuthorised ( User, Action ) as ?????...
25
by: lovecreatesbeauty | last post by:
Could you talk something about the general rules on the interface (function) design in C program that recognized publically? Or introduce some good advice of yourself. How do you think about...
2
by: Jeff | last post by:
Hello, I assigned a new object to a local variable ("req") in a function (see below). The local variable "req" is obviously destroyed when the function exits, but should the object referenced by...
9
by: tai | last post by:
Hi. I'm looking for a way to define a function that's only effective inside specified function. Featurewise, here's what I want to do: bar_plugin_func = function() { ...; setTimeout(...);...
5
by: StephQ | last post by:
This is from a thread that I posted on another forum some days ago. I didn't get any response, so I'm proposing it in this ng in hope of better luck :) The standard explanation is that pointer...
4
by: DaTurk | last post by:
Hi, I have this windows app that I'm working on. When it loads it instantiates this object which creates a thread to read data and send it to the form. My problem is, is that I want to keep...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each...
0
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing,...
0
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.