473,320 Members | 1,876 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,320 software developers and data experts.

Cleanup patterns

MQ
Hi all

I am just wondering how most people implement cleanup in C functions.
In particular, if the function opens a number of resources, these need
to be released properly should an error occur at any point in the
function (as well as at the end if successful). C++ has exceptions,
the only way I can see to do this neatly in C is to use goto
statements. Is my method of implementing cleanup good, or are their
better ways. Here is an example, which uses the global errno to store
the error.

#define CLEANUP(err) ({errno = (err); goto cleanup})

int example_function()
{
SOMETYPE * a,b,c;
errno = 0;

if(!(a = malloc(sizeof(a))))
CLEANUP(ENOMEM);

if(!(b = malloc(sizeof(b))))
CLEANUP(ENOMEM);

if(!(c = malloc(sizeof(c))))
CLEANUP(ENOMEM);

/* do something here */

cleanup:
if(a)
free(a);
if(b);
free(b);
if(c)
free(c);
if(errno)
return -1;
return 0;
}

Nov 29 '06
69 3142
Bill Reid wrote:
>
This is not exactly an academic exercise for me, since a lot of the
code I work with takes several HOURS to run on a Pentium-class
machine, and I have to run it EVERY day.
Maybe it's time for a 64 bit upgrade!

--
Ian Collins.
Dec 11 '06 #51
rp*****@yahoo.com (Roland Pibinger) writes:
On Mon, 11 Dec 2006 07:41:06 GMT, Richard Bos wrote:
>>The problem with xmalloc()-like functions is that they crash anyway;
they just crash with a predictable message.

They don't crash the program, they call exit (which also calls
atexit).
>>This _may_ be good enough,
but IMO not nearly as often as I see it done in the wild.

In order to run your program primarily needs one resource, memory.
Along with a number of other resources.
When it runs out of memory (e.g. due to a memory leak) there is hardly
anything you can do except to (more or less) gracefully terminate the
program.
That's not always true; it depends on the application. Somebody
already posted an example of an interactive editor failing to allocate
enough memory to load an image; the proper response is to issue a
diagnostic and continue running, not to crash the program.
Not even that is always possible since some OS (IIRC, Linux)
never return NULL for malloc even when memory is exhausted.
That behavior is arguably non-conforming.

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <* <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
Dec 11 '06 #52
Keith Thompson said:
rp*****@yahoo.com (Roland Pibinger) writes:
> Not even that is always possible since some OS (IIRC, Linux)
never return NULL for malloc even when memory is exhausted.

That behavior is arguably non-conforming.
I would have no doubt about that - it's non-conforming. What I would
question is the OP's claim that Linux over-commits. It is true that it can
be configured to over-commit, but certainly my installation is not
configured that way by default.

--
Richard Heathfield
"Usenet is a strange place" - dmr 29/7/1999
http://www.cpax.org.uk
email: rjh at the above domain, - www.
Dec 11 '06 #53
Keith Thompson wrote:
rp*****@yahoo.com (Roland Pibinger) writes:
On Mon, 11 Dec 2006 07:41:06 GMT, Richard Bos wrote:
>The problem with xmalloc()-like functions is that they crash anyway;
they just crash with a predictable message.
They don't crash the program, they call exit (which also calls
atexit).
>This _may_ be good enough,
but IMO not nearly as often as I see it done in the wild.
In order to run your program primarily needs one resource, memory.

Along with a number of other resources.
When it runs out of memory (e.g. due to a memory leak) there is hardly
anything you can do except to (more or less) gracefully terminate the
program.

That's not always true; it depends on the application. Somebody
already posted an example of an interactive editor failing to allocate
enough memory to load an image; the proper response is to issue a
diagnostic and continue running, not to crash the program.
Not even that is always possible since some OS (IIRC, Linux)
never return NULL for malloc even when memory is exhausted.

That behavior is arguably non-conforming.
To what standard? Linux's behaviour is outside the scope of the C
standard. Nevertheless, by never returning NULL, even when memory is
not available, it does make the malloc() implementation non-conforming.

Actually since from within the standard C program you cannot find out
_if_ memory is available or not, malloc()'s behaviour under OSes like
Linux is not non-conforming. It's doing it's job correctly, it just so
happens that it's subverted by forces outside it's control, (and the
standard's.)

Dec 11 '06 #54
santosh said:
Keith Thompson wrote:
>rp*****@yahoo.com (Roland Pibinger) writes:
Not even that is always possible since some OS (IIRC, Linux)
never return NULL for malloc even when memory is exhausted.

That behavior is arguably non-conforming.

To what standard?
ISO/IEC 9899. Some people view the operating system as being part of the
implementation. This is a not unreasonable view, although it's a bit hard
on compiler-writers if they have no control over the behaviour of the OS on
their platform...

--
Richard Heathfield
"Usenet is a strange place" - dmr 29/7/1999
http://www.cpax.org.uk
email: rjh at the above domain, - www.
Dec 11 '06 #55

Richard Heathfield wrote:
santosh said:
Keith Thompson wrote:
rp*****@yahoo.com (Roland Pibinger) writes:

Not even that is always possible since some OS (IIRC, Linux)
never return NULL for malloc even when memory is exhausted.

That behavior is arguably non-conforming.
To what standard?

ISO/IEC 9899. Some people view the operating system as being part of the
implementation.
<snip>

Yes well, in that case we can add the hardware and the rest of the
physical universe as part of the implementation too.

:)

Dec 11 '06 #56
"santosh" <sa*********@gmail.comwrites:
Richard Heathfield wrote:
>santosh said:
Keith Thompson wrote:
rp*****@yahoo.com (Roland Pibinger) writes:

Not even that is always possible since some OS (IIRC, Linux)
never return NULL for malloc even when memory is exhausted.

That behavior is arguably non-conforming.

To what standard?

ISO/IEC 9899. Some people view the operating system as being part of the
implementation.
<snip>

Yes well, in that case we can add the hardware and the rest of the
physical universe as part of the implementation too.

:)
Yes.

An implementation that doesn't meet the requirements of the standard
is non-conforming. Having a good excuse for the non-conformance
doesn't make it conforming.

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <* <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
Dec 11 '06 #57
Richard Bos wrote:
rp*****@yahoo.com (Roland Pibinger) wrote:
>On Sat, 09 Dec 2006 12:47:38 -0500, CBFalconer wrote:
>>Consider a big sort where the
input mechanism collects records in a linked list until memory is
exhauseted, mergesorts the list, dumps it to a temporary file,
discards the list, and repeats, dumping to the next temporary
file. When the input is exhausted it mergest the set of
temporaries into an output file.

Isn't there an external mergesort?

Yes. But they're typically a lot slower than internal sorts, so you
don't use it until you _know_ that you need it. Hence the check on
malloc().
The relative slowness is because the external sort is primarily
dependant on the i/o processing. You can get remarkable
performance by minimizing that i/o. See Wirths "Algorithms + Data
Structures = Programs" for polyphase sort. Triggering virtual
memory operation will foul that up quite nicely.

--
Chuck F (cbfalconer at maineline dot net)
Available for consulting/temporary embedded and systems.
<http://cbfalconer.home.att.net>
Dec 11 '06 #58
Roland Pibinger wrote:
On Mon, 11 Dec 2006 07:41:06 GMT, Richard Bos wrote:
>The problem with xmalloc()-like functions is that they crash
anyway; they just crash with a predictable message.

They don't crash the program, they call exit (which also calls
atexit).
>This _may_ be good enough,
but IMO not nearly as often as I see it done in the wild.

In order to run your program primarily needs one resource, memory.
When it runs out of memory (e.g. due to a memory leak) there is
hardly anything you can do except to (more or less) gracefully
terminate the program. Not even that is always possible since some
OS (IIRC, Linux) never return NULL for malloc even when memory is
exhausted.
Not so. I gave an example (external sort) upthread. To misquote
Dan Pop, engage brain before aborting.

--
Chuck F (cbfalconer at maineline dot net)
Available for consulting/temporary embedded and systems.
<http://cbfalconer.home.att.net>
Dec 11 '06 #59
santosh wrote:
Keith Thompson wrote:
>rp*****@yahoo.com (Roland Pibinger) writes:
.... snip ...
>>
>>Not even that is always possible since some OS (IIRC, Linux)
never return NULL for malloc even when memory is exhausted.

That behavior is arguably non-conforming.

To what standard? Linux's behaviour is outside the scope of the C
standard. Nevertheless, by never returning NULL, even when memory
is not available, it does make the malloc() implementation
non-conforming.

Actually since from within the standard C program you cannot find
out _if_ memory is available or not, malloc()'s behaviour under
OSes like Linux is not non-conforming. It's doing it's job
correctly, it just so happens that it's subverted by forces
outside it's control, (and the standard's.)
Again, not necessarily. There is no speed requirement, so an OS
can simply postpone program execution until the memory is actually
available. Implementing this could run into the deadly embrace
problem.

--
Chuck F (cbfalconer at maineline dot net)
Available for consulting/temporary embedded and systems.
<http://cbfalconer.home.att.net>

Dec 11 '06 #60
CBFalconer wrote:
Keith Thompson wrote:
... snip ...
waste of time -- just as any insurance policy that doesn't pay off
is a waste of money. (Life insurance is a really bad deal if you
happen to be immortal.)

Now I know why I haven't had any for the past 20 years :-)
Because you're immortal? Wow.
(Apart
from the Social Security death 'benefit').

I have some freebie insurance from work, some multiplier times your
yearly salary.

Brian
Dec 11 '06 #61
"Default User" <de***********@yahoo.comwrites:
CBFalconer wrote:
>Keith Thompson wrote:
>
... snip ...
waste of time -- just as any insurance policy that doesn't pay off
is a waste of money. (Life insurance is a really bad deal if you
happen to be immortal.)

Now I know why I haven't had any for the past 20 years :-)

Because you're immortal? Wow.
So far ...

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <* <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
Dec 11 '06 #62
Keith Thompson wrote:
"Default User" <de***********@yahoo.comwrites:
>CBFalconer wrote:
>>Keith Thompson wrote:

... snip ...
waste of time -- just as any insurance policy that doesn't pay off
is a waste of money. (Life insurance is a really bad deal if you
happen to be immortal.)

Now I know why I haven't had any for the past 20 years :-)

Because you're immortal? Wow.

So far ...
Well, I only have experience to go by, and so far there have been
no exceptions. I've had a couple of near misses lately though. Is
this an omen? Maybe we need an ISO standard for reference.

--
Chuck F (cbfalconer at maineline dot net)
Available for consulting/temporary embedded and systems.
<http://cbfalconer.home.att.net>
Dec 11 '06 #63
rp*****@yahoo.com (Roland Pibinger) wrote:
On Mon, 11 Dec 2006 07:41:06 GMT, Richard Bos wrote:
The problem with xmalloc()-like functions is that they crash anyway;
they just crash with a predictable message.

They don't crash the program, they call exit (which also calls
atexit).
To the end user, it's usually all the same.
This _may_ be good enough,
but IMO not nearly as often as I see it done in the wild.

In order to run your program primarily needs one resource, memory.
When it runs out of memory (e.g. due to a memory leak)
Well, _yes_. If you assume rampant bug that no C programmer should let
into a production program any more (and, therefore, some famous
companies regularly do), you might as well terminate the program there
and then. In fact, why not be pro-active, and terminate it at random
intervals?
there is hardly anything you can do except to (more or less)
gracefully terminate the program.
As shown upthread, for a _well written_ program, this is simply untrue.
It _may_ be the case, but often you have better options.
Not even that is always possible since some OS (IIRC, Linux)
never return NULL for malloc even when memory is exhausted.
Those OSes are broken. If you can't trust your OS not to lie to you, why
trust your computer at anything?

Richard
Dec 12 '06 #64
On Mon, 11 Dec 2006 09:30:03 GMT, Keith Thompson wrote:
>That behavior is arguably non-conforming.
<offtopic>
When Linux Runs Out of Memory
http://www.linuxdevcenter.com/lpt/a/6808
</offtopic>
Dec 16 '06 #65
Roland Pibinger wrote:
On Mon, 11 Dec 2006 09:30:03 GMT, Keith Thompson wrote:
>That behavior is arguably non-conforming.

<offtopic>
When Linux Runs Out of Memory
http://www.linuxdevcenter.com/lpt/a/6808
</offtopic>
<offtopic>
http://lwn.net/Articles/104179/
</offtopic>

--
Eric Sosman
es*****@acm-dot-org.invalid
Dec 16 '06 #66
Eric Sosman wrote
(in article <P8******************************@comcast.com>):
http://lwn.net/Articles/104179/
OT, Perhaps. Hilarious? Definitely.

Over-engineering a solution to a problem that doesn't even need
to exist.

--
Randy Howard (2reply remove FOOBAR)
"The power of accurate observation is called cynicism by those
who have not got it." - George Bernard Shaw

Dec 16 '06 #67

sl*******@yahoo.com <sl*******@gmail.comwrote in message
news:11**********************@79g2000cws.googlegro ups.com...
Bill Reid wrote:
Richard Heathfield <rj*@see.sig.invalidwrote in message
news:fr******************************@bt.com...
MQ said:
Bill Reid wrote:

For more complex functions, you'll quite often have contigent
dependancies for each resource acquisition that don't fit neatly
into
the "nest", and the overhead of the function calling mechanism
means that functions are not infinitely or always a "fabulous
mechanism" for something as silly as "keeping the indent
level down" (unless you like your "C" code to run as slow
as "Java"!).

These are my greatest concerns, as I am writing file system driver
code
that needs to be fast efficient.
>
Rule 1: if it doesn't work, it doesn't matter how fast it is.
Rule 2: it is easier to make a correct program fast than it is to make
a
fast program correct.
Rule 3: it is easier to make a readable program correct than it is to
make
a
correct program readable.
>
I think these are actually the three rules for pontificating about
programming instead of actually programming...years ago I read
the REAL rules for writing "correct" "fast" and "efficient" code, and
of course, as everybody who's not just pontificating knows,
it boils down to one general rule: pick the two you really want, because
a lot of times you CAN'T have all three...
And that's before we get anywhere near the Two Rules of
Micro-Optimisation.
For completeness, these are:
>
Rule 1: Don't do it.
Rule 2 (for experts only): Don't do it yet.
>
I certainly wasn't talking about anything like "micro-optimization".
I'm talking about great big gobs of "MACRO-optimization", like
slowing down or speeding up what was virtually the IDENTICAL
code by a factor of up to ten-fold (I could make the same program run
in either two seconds or 20 seconds)...

On a lot of modern CPUs the difference between a function call and a
jump (as in generated by switch or if) is nowhere near ten-fold when
compiled with an properly optimising compiler. One fold at most (note
that one-fold is ten times slower)
OK, I'm officially confused...I specifically said "two seconds or 20
seconds" as being "ten-fold" (as in, a thousand is a hundred "ten-fold"),
then you re-define "fold" as "ten times slower". So what you're saying
is that with a "properly optimising compiler", a function call is UP TO
"ten times slower"...which is basically what I was always told, it takes
somewhere around 4-8 extra cycles as overhead for a function call,
so I think we don't have a disagreement there?
or more typically up to 4 times
slower.
"6" was the magic number I was told (or actually read) to work with...
Indeed on at least two architectures I code for, a function
call (if not recursive) compiles to execute in exactly the same number
of CPU cycles as a regular jump/branch.
This may be true, and I don't doubt that it depends on the specific
function call and optimization "tricks" of the compiler in any event...
This is not exactly an academic exercise for me, since a lot of the
code I work with takes several HOURS to run on a Pentium-class
machine, and I have to run it EVERY day.

Of course, if you're programming for an architecture as archaic and
register-starved as the Pentium then function call overhead can be an
issue.
Yeah, slam the Pentium, then go ahead and slam "MIPS" and "SPARC"
while you're at it, since I've been able to significantly speed up or slow
down programs on all of them (in many cases, the exact same program
on all the different architectures).
Even so, improvements have been made to x86-64 which makes the
function call overhead for x86-64 even less than before.
I will admit that the ever-increasing power and speed of computer
hardware does make a lot of these considerations practically moot...but
that still doesn't excuse how I saw people coding back when it made
a TREMENDOUS practical difference, and these WERE what had
to be considered the elite systems software engineers in the entire
world...

---
William Ernest Reid

Dec 29 '06 #68

Ian Collins <ia******@hotmail.comwrote in message
news:4u*************@mid.individual.net...
Bill Reid wrote:

This is not exactly an academic exercise for me, since a lot of the
code I work with takes several HOURS to run on a Pentium-class
machine, and I have to run it EVERY day.

Maybe it's time for a 64 bit upgrade!
Then I'll re-write it all in Java!

---
William Ernest Reid

Dec 29 '06 #69
Bill Reid wrote:
sl*******@yahoo.com <sl*******@gmail.comwrote in message
news:11**********************@79g2000cws.googlegro ups.com...
Bill Reid wrote:
I certainly wasn't talking about anything like "micro-optimization".
I'm talking about great big gobs of "MACRO-optimization", like
slowing down or speeding up what was virtually the IDENTICAL
code by a factor of up to ten-fold (I could make the same program run
in either two seconds or 20 seconds)...
On a lot of modern CPUs the difference between a function call and a
jump (as in generated by switch or if) is nowhere near ten-fold when
compiled with an properly optimising compiler. One fold at most (note
that one-fold is ten times slower)

OK, I'm officially confused...I specifically said "two seconds or 20
seconds" as being "ten-fold" (as in, a thousand is a hundred "ten-fold"),
then you re-define "fold" as "ten times slower".
Sorry, I was confusing "fold" with "orders of magnitude". Fold, proper,
commonly means multiplication by that factor which makes what you said
correct and what I said wrong.
or more typically up to 4 times
slower.

"6" was the magic number I was told (or actually read) to work with...
Indeed on at least two architectures I code for, a function
call (if not recursive) compiles to execute in exactly the same number
of CPU cycles as a regular jump/branch.
This may be true, and I don't doubt that it depends on the specific
function call and optimization "tricks" of the compiler in any event...
On a lot of modern architectures (this excludes x86-32 although it
includes x86-64) this is quite trivial (see below).
This is not exactly an academic exercise for me, since a lot of the
code I work with takes several HOURS to run on a Pentium-class
machine, and I have to run it EVERY day.
Of course, if you're programming for an architecture as archaic and
register-starved as the Pentium then function call overhead can be an
issue.
Even so, improvements have been made to x86-64 which makes the
function call overhead for x86-64 even less than before.
I will admit that the ever-increasing power and speed of computer
hardware does make a lot of these considerations practically moot...but
The point is not the speed of the hardware. No matter how fast the
hardware becomes a ten fold slowdown is STILL a ten fold slowdown. The
point is that x86-64 is not register starved allowing the compiler to
avoid using stacks to pass parameters and especially for the kind of
trivial functions we were discussing can also allow the compiler to do
*nothing* to pass parameters via overlays.

Hence for the kinds of functions we're discussing (small utility
functions to reduce indentation, remember that we're not discussing
function calling *in general*) passing parameters can be optimised to
generate zero instructions and calling the function itself generates
one instruction. On most modern machines that instruction takes the
same amount of time to execute as a conditional branch.
that still doesn't excuse how I saw people coding back when it made
a TREMENDOUS practical difference, and these WERE what had
to be considered the elite systems software engineers in the entire
world...
And now we have the conclusion. Your trick programming and inlining
WERE useful in the age of dino-mainframes where workstation CPUs were
nothing more than glorified microcontrollers. Today even lowly 50 cent
microcontrollers don't break a sweat executing deeply nested function
calls (unless you're doing something silly like directly generating
video signals on output pins without the help of graphics hardware).

Dec 30 '06 #70

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

Similar topics

2
by: Design Pattern Catalog | last post by:
Thank you for your interest in "Design Patterns: Elements of Reusable Object-Oriented Design", by Erich Gamma, Richard Helm, Ralph Johnson, and John Vlissides. This message answers several...
6
by: use dmgass at hotmail dot com | last post by:
I'm writing a module and when it is imported by a script I want some code automatically executed when the importing script is finished executing. I'd like it to execute before interactive mode is...
32
by: fatted | last post by:
I've written a function (clean_string) to remove characters from a string, but it looks clunky to me, and I'm sure there's a more 'C' like way of doing it (still learning), comments and advice...
1
by: Jay | last post by:
The GOF text is widely considered the definitive book on the topic. Design Patterns: Elements of Reusable Object-Oriented Softare, Erich Gamma, Richard Helm, Ralph Johnson, John Vlissides ...
13
by: John Salerno | last post by:
Here are a few I'm considering: Design Patterns Explained : A New Perspective on Object-Oriented Design (2nd Edition) (Software Patterns Series) by Alan Shalloway Design Patterns C# by...
12
by: Jeff | last post by:
I'm just getting up to speed on OOP patterns (e.g, MVC) and I'm wondering how closely they are followed out in the real world. Do those of you who use them try to follow them as closely as possible...
1
by: Jason S | last post by:
I haven't used try/catch/finally very much in Javascript. My function (let's call it try_it()) needs to call a function that could throw an exception (let's call it dangerous()) with some setup()...
7
by: =?Utf-8?B?bWF2cmlja18xMDE=?= | last post by:
Hi, I would like to know more about design patterns and specifically using C#. Can any one recommend a good book? Thanks
4
by: IanWright | last post by:
I've got a section of a program that I can't quite get to work. I'm fairly sure its something very simple/trivial but it looks correct to me, so if someone could help me fix the problem, and explain...
0
by: ryjfgjl | last post by:
ExcelToDatabase: batch import excel into database automatically...
0
isladogs
by: isladogs | last post by:
The next Access Europe meeting will be on Wednesday 6 Mar 2024 starting at 18:00 UK time (6PM UTC) and finishing at about 19:15 (7.15PM). In this month's session, we are pleased to welcome back...
1
isladogs
by: isladogs | last post by:
The next Access Europe meeting will be on Wednesday 6 Mar 2024 starting at 18:00 UK time (6PM UTC) and finishing at about 19:15 (7.15PM). In this month's session, we are pleased to welcome back...
0
by: Vimpel783 | last post by:
Hello! Guys, I found this code on the Internet, but I need to modify it a little. It works well, the problem is this: Data is sent from only one cell, in this case B5, but it is necessary that data...
0
by: ArrayDB | last post by:
The error message I've encountered is; ERROR:root:Error generating model response: exception: access violation writing 0x0000000000005140, which seems to be indicative of an access violation...
1
by: PapaRatzi | last post by:
Hello, I am teaching myself MS Access forms design and Visual Basic. I've created a table to capture a list of Top 30 singles and forms to capture new entries. The final step is a form (unbound)...
0
by: Shællîpôpï 09 | last post by:
If u are using a keypad phone, how do u turn on JavaScript, to access features like WhatsApp, Facebook, Instagram....
0
by: af34tf | last post by:
Hi Guys, I have a domain whose name is BytesLimited.com, and I want to sell it. Does anyone know about platforms that allow me to list my domain in auction for free. Thank you
0
by: Faith0G | last post by:
I am starting a new it consulting business and it's been a while since I setup a new website. Is wordpress still the best web based software for hosting a 5 page website? The webpages will be...

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.