468,463 Members | 2,058 Online
Bytes | Developer Community
New Post

Home Posts Topics Members FAQ

Post your question to a community of 468,463 developers. It's quick & easy.

A solution for the allocation failures problem

1:
It is not possible to check EVERY malloc result within complex software.

2:
The reasonable solution (use a garbage collector) is not possible for
whatever reasons.

3:
A solution like the one proposed by Mr McLean (aborting) is not
possible for software quality reasons. The program must decide
if it is possible to just abort() or not.

Solution:

1) At program start, allocate a big buffer that is not used
elsewhere in the program. This big buffer will be freed when
a memory exhaustion situation arises, to give enough memory
to the error reporting routines to close files, or otherwise
do housekeeping chores.

2) xmalloc()

static int (*mallocfailedHandler)(int);
void *xmalloc(size_t nbytes)
{
restart:
void *r = malloc(nbytes);
if (r)
return r;
// Memory exhaustion situation.
// Release some memory to the malloc/free system.
if (BigUnusedBuffer)
free(BigUnusedBuffer);
BigUnusedBuffer = NULL;
if (mallocfailedHandler == NULL) {
// The handler has not been set. This means
// this application does not care about this
// situation. We exit.
fprintf(stderr,
"Allocation failure of %u bytes\n",
nbytes);
fprintf(stderr,"Program exit\n");
exit(EXIT_FAILURE);
}
// The malloc handler has been set. Call it.
if (mallocfailedHandler(nbytes)) {
goto restart;
}
// The handler failed to solve the problem.
// Exit without any messages.
exit(EXIT_FAILURE);
}

4:
Using the above solution the application can abort if needed, or
make a long jump to a recovery point, where the program can continue.

The recovery handler is supposed to free memory, and reallocate the
BigUnusedBuffer, that has been set to NULL;
--
jacob navia
jacob at jacob point remcomp point fr
logiciels/informatique
http://www.cs.virginia.edu/~lcc-win32
Jan 29 '08
158 4690
Ian Collins <ia******@hotmail.comwrote:
char* p0 = malloc(100);
char* p1 = malloc(200);
char* p2 = malloc(300);

What do you do if the second malloc throws?
In my C code, I typically use a pattern something like this:

int ReturnValue = SUCCESS;
char *p0 = NULL;
char *p1 = NULL;
char *p2 = NULL;

if ((p0 = malloc(100)) == NULL)
{
ReturnValue = ENOMEM;
goto ExitFunction;
}

if ((p1 = malloc(200)) == NULL)
{
ReturnValue = ENOMEM;
goto ExitFunction;
}

if ((p2 = malloc(300)) == NULL)
{
ReturnValue = ENOMEM;
goto ExitFunction;
}

/* Do some work with the allocated memory */

ExitFunction:

free(p0);
free(p1);
free(p2);

return ReturnValue;
Feb 8 '08 #101
Ioannis Vranos wrote:
Ioannis Vranos wrote:
>Ian Collins wrote:
>>>
That's not as easy as it sounds in C. C++ has the built in mechanisms
to write exception safe code. Such code is hard to write in C (the same
issues as multiple points of return).

Consider

char* p0 = malloc(100);
char* p1 = malloc(200);
char* p2 = malloc(300);

What do you do if the second malloc throws?

You'd end up with as much if not more code for a series of try/catch
blocks as you would for a series of if() blocks.


You can retrieve information about what failed from the exception itself.


More specifically you may apply try-catch to each of the malloc
statements, you can apply try-catch to the whole block of malloc
statements, you can apply try-catch to the entire function body, or you
can apply try-catch inside a caller function.
The first is no different from individual if() blocks, the second two leak.
You do not need to return failure values from called functions to
callers, it is done automatically if you do not catch the exception.
As I said before, it's very hard and therefore error prone to write
exception safe code with the mechanisms C provides for all of the
reasons it's very hard to use multiple points of return. Square that
when exceptions can escape out of functions.

--
Ian Collins.
Feb 8 '08 #102
On Feb 8, 12:51 pm, Richard Heathfield <r...@see.sig.invalidwrote:
ymunt...@gmail.com said:
On Feb 8, 7:34 am, Richard Heathfield <r...@see.sig.invalidwrote:
Ioannis Vranos said:
Richard Heathfield wrote:
Right. It is certainly the case that nobody writes perfect code, but
there's nothing particularly special about malloc - it's just a way
of requesting a resource, very similar in that respect to fopen. I
don't hear anyone arguing that it's impossible to deal with fopen
failures.
Exceptions can be used for all kinds of resource allocations.
Well, we don't actually have exceptions in C, so no, they can't. And
we're not likely to get them, either.
This whole thread seems to be based on the fallacy that if(mp != NULL)
is harder to type than if(fp != NULL).
And so I went to look for best practices, got some C code from
http://www.cpax.org.uk/prg/portable/...x.php#download
It handles malloc() failure pretty well: the function which calls
malloc() returns NULL, and its caller happily uses some default
value instead of what it's supposed to do. But it does "handle"
malloc() failure.

That could be done better, I agree. But to crash and burn would be worse,
not better.
Exit with a failure status would be worse?
Sure, from such a toy program you shouldn't expect much intelligence
(though it could fail instead of saying "all is well"), but we
are talking here "easy to type", aren't we? Or do I miss something,
and it's really not about handling errors but about typing an
"if(mp != NULL)"?
A bonus question: what happens when malloc() fails inside fgetline()
(my hypothesis: nothing, we pretend we hit EOF. But we don't "crash
and burn", which is Good)

Your hypothesis is incorrect; fgetline returns a non-zero error code for an
allocation failure (it happens to be -3, which I really ought to wrap in a
#define). A generic routine such as fgetline can't reasonably decide what
to do on allocation failure, so it has only two options - crash and burn,
or tell the caller. Crash-and-burn would be stupid, so we tell the caller.
fgetline() returns an error, yes. What does it caller do?
The caller thinks it hit EOF (that's my hypothesis).

Anyway, the point is: it's not about how it is easy or hard to
type "if (whatever)". It's very easy to type. Here, we have
a program which has that easy to type line. Does it do the
right thing? No. What does it mean? It means that putting
an if() doesn't make your code right.

Oh, and to make sure I'm in your killfile again: fix your code
then talk about incompetence of others.

Yevgen
Feb 8 '08 #103
Ed Jensen wrote:
Ian Collins <ia******@hotmail.comwrote:
>char* p0 = malloc(100);
char* p1 = malloc(200);
char* p2 = malloc(300);

What do you do if the second malloc throws?

In my C code, I typically use a pattern something like this:

int ReturnValue = SUCCESS;
char *p0 = NULL;
char *p1 = NULL;
char *p2 = NULL;

if ((p0 = malloc(100)) == NULL)
{
ReturnValue = ENOMEM;
goto ExitFunction;
}
But what if you acquire something here...
if ((p1 = malloc(200)) == NULL)
{
ReturnValue = ENOMEM;
goto ExitFunction;
}
and release it here?
if ((p2 = malloc(300)) == NULL)
{
ReturnValue = ENOMEM;
goto ExitFunction;
}

/* Do some work with the allocated memory */

ExitFunction:

free(p0);
free(p1);
free(p2);

return ReturnValue;

--
Ian Collins.
Feb 8 '08 #104
Richard Heathfield <rj*@see.sig.invalidwrote:
>It's based on the fact that in most applications, dynamic memory is
allocated (and freed) a lot.

In most applications, information comes in via streams and goes out via
streams, a lot (otherwise where are you getting your data and where are
you putting the results?). But nobody is bothering to propose a "solution
for the read/write failures problem" (and rightly so, because there isn't
such a problem). The fact that malloc is called a lot is not an excuse for
calling it badly.
Garbage collection was largely conceived and now enjoys great success
in part due to the fact that many (most?) applications allocate and
free dynamic memory a lot.

i.e., It was recognized as a resource that can (and often should) be
treated specially.

I think you're being intellectually dishonest when trying to compare
it to other resources (such as files). There are similarities, of
course, but it's likely that most applications allocate and free
memory much more often than they open and close files.
Feb 8 '08 #105
Randy Howard <ra*********@fooverizonbar.netwrote:
Just give them time. It won't be long before someone argues that
checking return values fopen() is impossible to do correctly, so don't
even try.
It's sad to see this thread continue to include so many childish
insults.
Feb 8 '08 #106
Randy Howard <ra*********@fooverizonbar.netwrote:
>I think that peer review is a useful thing. But, as with all efforts,
it is VERY expensive (10-12 programmers doing peer review!)

Quite the opposite. It's very cost-effective. You just need to
contrast that cost with what it takes to fix, repair and support
hundreds, thousands or millions of customers in the field that are
suddenly experiencing bugs and demanding fixes, and perhaps even
threatening legal action.
Theoretically, the free market will decide which development practices
are most cost effective. Just look at successful software companies
and determine how much peer review they do. (Of course, some software
companies may cheat by illegally leveraging their monopoly, so you'd
have to pick and choose which companies to review very carefully.)
Feb 8 '08 #107
Ian Collins <ia******@hotmail.comwrote:
>In my C code, I typically use a pattern something like this:

int ReturnValue = SUCCESS;
char *p0 = NULL;
char *p1 = NULL;
char *p2 = NULL;

if ((p0 = malloc(100)) == NULL)
{
ReturnValue = ENOMEM;
goto ExitFunction;
}
But what if you acquire something here...
>if ((p1 = malloc(200)) == NULL)
{
ReturnValue = ENOMEM;
goto ExitFunction;
}
and release it here?
>if ((p2 = malloc(300)) == NULL)
{
ReturnValue = ENOMEM;
goto ExitFunction;
}

/* Do some work with the allocated memory */

ExitFunction:

free(p0);
free(p1);
free(p2);

return ReturnValue;
I would use the same strategy, except the code following the
ExitFunction label would look a little different. For example:

ExitFunction:

free(p0);
free(p1);
if (fp != NULL) { fclose(fp); }
free(p2);

return ReturnValue;

That is, I'd just let the clean up code determine whether or not the
resource still needed to be cleaned up.
Feb 8 '08 #108
Ed wrote:
) Theoretically, the free market will decide which development practices
) are most cost effective.

Hiring the cheapest possible developers and pushing out code that
is 'just about good enough' would seem most cost effective, then.
SaSW, Willem
--
Disclaimer: I am in no way responsible for any of the statements
made in the above text. For all I know I might be
drugged or something..
No I'm not paranoid. You all think I'm paranoid, don't you !
#EOT
Feb 8 '08 #109
Ed Jensen wrote:
>
Ian Collins <ia******@hotmail.comwrote:
char* p0 = malloc(100);
char* p1 = malloc(200);
char* p2 = malloc(300);

What do you do if the second malloc throws?

In my C code, I typically use a pattern something like this:

int ReturnValue = SUCCESS;
char *p0 = NULL;
char *p1 = NULL;
char *p2 = NULL;

if ((p0 = malloc(100)) == NULL)
{
ReturnValue = ENOMEM;
goto ExitFunction;
}

if ((p1 = malloc(200)) == NULL)
{
ReturnValue = ENOMEM;
goto ExitFunction;
}

if ((p2 = malloc(300)) == NULL)
{
ReturnValue = ENOMEM;
goto ExitFunction;
}

/* Do some work with the allocated memory */

ExitFunction:

free(p0);
free(p1);
free(p2);

return ReturnValue;
In situations like this, I typically do something like:

int retval = SUCCESS;
char *p0, *p1, *p2;

p0 = malloc(100);
p1 = malloc(200);
p2 = malloc(300);
if ( p0 == NULL || p1 == NULL || p2 == NULL )
{
retval = FAILURE;
goto ret;
}

/* do stuff */

ret:

free(p0);
free(p1);
free(p2);
return retval;

Of course, this is a simple case where nothing happens between the
mallocs, and failure handling doesn't matter which one failed. But,
that's not entirely rare.

Yes, I do use "goto" here, even though it could be avoided by placing
"do stuff" within an "else" in this case. Sometimes there are other
possible failures within "do stuff" which wouldn't be handled so
cleanly without the "goto".

--
+-------------------------+--------------------+-----------------------+
| Kenneth J. Brody | www.hvcomputer.com | #include |
| kenbrody/at\spamcop.net | www.fptech.com | <std_disclaimer.h|
+-------------------------+--------------------+-----------------------+
Don't e-mail me at: <mailto:Th*************@gmail.com>
Feb 8 '08 #110
Ed Jensen wrote:

<snip>
>
I would use the same strategy, except the code following the
ExitFunction label would look a little different. For example:

ExitFunction:

free(p0);
free(p1);
if (fp != NULL) { fclose(fp); }
free(p2);

return ReturnValue;

That is, I'd just let the clean up code determine whether or not the
resource still needed to be cleaned up.
Workable, but you can see the complexity of the code increasing along
with the risk of error. The maintenance programmer will have to take
great care when added code between exit points.

--
Ian Collins.
Feb 8 '08 #111
Ian Collins <ia******@hotmail.comwrote:
Ed Jensen wrote:
>I would use the same strategy, except the code following the
ExitFunction label would look a little different. For example:

ExitFunction:

free(p0);
free(p1);
if (fp != NULL) { fclose(fp); }
free(p2);

return ReturnValue;

That is, I'd just let the clean up code determine whether or not the
resource still needed to be cleaned up.

Workable, but you can see the complexity of the code increasing along
with the risk of error. The maintenance programmer will have to take
great care when added code between exit points.
I'm open to alternatives. :)
Feb 8 '08 #112
ym******@gmail.com said:
On Feb 8, 12:51 pm, Richard Heathfield <r...@see.sig.invalidwrote:
<snip>
>A generic routine such as fgetline can't reasonably decide
what to do on allocation failure, so it has only two options - crash and
burn, or tell the caller. Crash-and-burn would be stupid, so we tell the
caller.

fgetline() returns an error, yes. What does it caller do?
The caller thinks it hit EOF (that's my hypothesis).
Oh, I see - fair enough. Yes, the test is against 0, and doesn't handle
malloc failure separately. It ought to. That's a weakness in the program
(not the library), which I ought to remedy. In fact, I was just looking
over the code again, and spotted it's not the only way in which emgen
needs fixing. When I get some time, I'll do something about that.
Oh, and to make sure I'm in your killfile again: fix your code
then talk about incompetence of others.
I don't see why you think a reasonable complaint about my shoddy code would
land you in my killfile. As for "the incompetence of others", incompetence
can be rooted in either (or both) of two problems - ignorance (not having
learned yet) or stupidity (refusing to put into practice the things one
ought to have learned). Ignorance is correctable (or corrigible, perhaps)
and forgivable. Stupidity is harder to correct and less forgivable.
Unfortunately for me, the emgen code shows definite signs of stupidity on
my part - so yes, I ought to go fix that code.

But when I do so, I will fix it to deal with allocation failures properly -
"crash and burn" should be a last resort, not a first response.

--
Richard Heathfield <http://www.cpax.org.uk>
Email: -http://www. +rjh@
Google users: <http://www.cpax.org.uk/prg/writings/googly.php>
"Usenet is a strange place" - dmr 29 July 1999
Feb 8 '08 #113
Richard Heathfield wrote:
ym******@gmail.com said:
>On Feb 8, 12:51 pm, Richard Heathfield <r...@see.sig.invalidwrote:

<snip>
>>A generic routine such as fgetline can't reasonably decide
what to do on allocation failure, so it has only two options - crash and
burn, or tell the caller. Crash-and-burn would be stupid, so we tell the
caller.
fgetline() returns an error, yes. What does it caller do?
The caller thinks it hit EOF (that's my hypothesis).

Oh, I see - fair enough. Yes, the test is against 0, and doesn't handle
malloc failure separately. It ought to. That's a weakness in the program
(not the library), which I ought to remedy. In fact, I was just looking
over the code again, and spotted it's not the only way in which emgen
needs fixing. When I get some time, I'll do something about that.
>Oh, and to make sure I'm in your killfile again: fix your code
then talk about incompetence of others.

I don't see why you think a reasonable complaint about my shoddy code would
land you in my killfile. As for "the incompetence of others", incompetence
can be rooted in either (or both) of two problems - ignorance (not having
learned yet) or stupidity (refusing to put into practice the things one
ought to have learned). Ignorance is correctable (or corrigible, perhaps)
and forgivable. Stupidity is harder to correct and less forgivable.
Unfortunately for me, the emgen code shows definite signs of stupidity on
my part - so yes, I ought to go fix that code.

But when I do so, I will fix it to deal with allocation failures properly -
"crash and burn" should be a last resort, not a first response.
Well Mr Heathfield, you were treating me of incompetent, and refusing
to accept the possibility that good programmers will always do some
kind of mistake *sometime*.

There you have the proof. The point is, that as we always add code and
code at each malloc call (and there *are* a lot of them), the
probability of making a mistake *increases*.

The solution I proposed in the starting post of this thread is not
"crash and burn" as you put it. The user can define an exit strategy
or recovery measures because a call back is called that the user can
modify at specific places in the code.

This would allow to flexibly modify the strategy when using more
memory for loading more data (no more data can be loaded, not
a fatal error) or when needing some memory to establish a
network connection (that would be a fatal error)

The advantage of that is that we have now a MUCH SMALLER code base to
review and we can concentrate on doing that small part right, instead
of putting the recovery code at each malloc usage, where there
is no possibility in most cases to change the strategy because no
information about the context is readily available.

--
jacob navia
jacob at jacob point remcomp point fr
logiciels/informatique
http://www.cs.virginia.edu/~lcc-win32
Feb 8 '08 #114
Ed Jensen wrote:
Ian Collins <ia******@hotmail.comwrote:
>Ed Jensen wrote:
>>I would use the same strategy, except the code following the
ExitFunction label would look a little different. For example:

ExitFunction:

free(p0);
free(p1);
if (fp != NULL) { fclose(fp); }
free(p2);

return ReturnValue;

That is, I'd just let the clean up code determine whether or not the
resource still needed to be cleaned up.
Workable, but you can see the complexity of the code increasing along
with the risk of error. The maintenance programmer will have to take
great care when added code between exit points.

I'm open to alternatives. :)
OK, I've got a tough skin...

For hosted applications that use a lot of dynamic memory I use TOL...

For embedded applications (my main use of C) I either

A) ban dynamic memory use

or

B) abort on failure as these systems are sized for the application and
any malloc failure is inevitably due to a leak.

My preference is for A. I've implemented the allocator on every
embedded product I've worked over the past 20 years, which has enabled
me to track usage and leaks. But I still prefer A!

--
Ian Collins.
Feb 8 '08 #115
Kenneth Brody <ke******@spamcop.netwrote:
In situations like this, I typically do something like:

int retval = SUCCESS;
char *p0, *p1, *p2;

p0 = malloc(100);
p1 = malloc(200);
p2 = malloc(300);
if ( p0 == NULL || p1 == NULL || p2 == NULL )
{
retval = FAILURE;
goto ret;
}

/* do stuff */

ret:

free(p0);
free(p1);
free(p2);
return retval;

Of course, this is a simple case where nothing happens between the
mallocs, and failure handling doesn't matter which one failed. But,
that's not entirely rare.
I like it. That's a nice shortcut. So is this:

char p0[100];
char p1[200];
char p2[300];

/* Etc. */

OK, I'm kidding, but only half kidding. What got me thinking about
this is the minor skirmishes re: ggets(), fgetline(), etc. in some
other threads.

Sometimes what makes the most sense is just picking a reasonable
buffer size in the first place.
Yes, I do use "goto" here, even though it could be avoided by placing
"do stuff" within an "else" in this case. Sometimes there are other
possible failures within "do stuff" which wouldn't be handled so
cleanly without the "goto".
In my opinion, there's nothing wrong with using goto appropriately,
and I think you used it appropriately.

For simple cases, sometimes I use this pattern:

do
{
if ((p0 = malloc(...)) == NULL)
{
retval = ENOMEM;
break;
}

/* Etc */
}
while (0);

/* Clean-up code goes here */

It avoids the goto, though I'm not convinced it makes the code any
more clear, especially when the contents of the do-while loop may go
beyond the height of your editor window, whereas "goto ExitFunction;"
or something similar is very clear.
Feb 8 '08 #116
Willem <wi****@stack.nlwrote:
Ed wrote:
) Theoretically, the free market will decide which development practices
) are most cost effective.

Hiring the cheapest possible developers and pushing out code that
is 'just about good enough' would seem most cost effective, then.
Actually, I think the market is finding out the exact opposite, slowly
but surely. Slowly, because executives don't want to admit when
they've made a bad decision, so they try to make their decision to
offshore or offshore outsource seem like it's truly saving money.
Feb 8 '08 #117
Ian Collins <ia******@hotmail.comwrote:
OK, I've got a tough skin...

For hosted applications that use a lot of dynamic memory I use TOL...
What's TOL?
For embedded applications (my main use of C) I either

A) ban dynamic memory use

or

B) abort on failure as these systems are sized for the application and
any malloc failure is inevitably due to a leak.

My preference is for A. I've implemented the allocator on every
embedded product I've worked over the past 20 years, which has enabled
me to track usage and leaks. But I still prefer A!
Sounds perfectly reasonable.
Feb 8 '08 #118
Ed Jensen wrote:
Ian Collins <ia******@hotmail.comwrote:
>OK, I've got a tough skin...

For hosted applications that use a lot of dynamic memory I use TOL...

What's TOL?
That Other Language (C++).

--
Ian Collins.
Feb 8 '08 #119

"Morris Dovey" <mr*****@iedu.comwrote in message
Ok - I think I understand, but don't recall seeing anything in
the Standard that /requires/ this reservation. Personally, I'd
hope that free()d memory would be re-absorbed by the OS (if
present) into global pool(s) so that it could be made available
to other processes/threads - and it seems to me inappropriate for
a programming language standard to dictate host memory resource
management in such a way. I guess my mileage varies on this
issue.
That's a grey area.
There would be little or no point in calling free() at all if memory was
still hogged by the malloc() system. The question is whether the program is
allowed or required to hog it.
In practise we cannot forbid programs from hogging resources until exit,
because of the limitations of some operating systems. However it seems more
in keeping with the ethos of multi-tasking to yeild memory you no longer
require.

--
Free games and programming goodies.
http://www.personal.leeds.ac.uk/~bgy1mm

Feb 8 '08 #120
In article <00*****************************@news.verizon.net> ,
Randy Howard <ra*********@FOOverizonBAR.netwrote:
>Just give them time. It won't be long before someone argues that
checking return values fopen() is impossible to do correctly, so don't
even try.
But in fact fopen() failure is far more likely to be due to user error
(notably, typing in the wrong file name), and thus more likely to be
recoverable.

-- Richard
--
:wq
Feb 8 '08 #121

"Richard Heathfield" <rj*@see.sig.invalidwrote in message
Ed Jensen said:

In most applications, information comes in via streams and goes out via
streams, a lot (otherwise where are you getting your data and where are
you putting the results?). But nobody is bothering to propose a "solution
for the read/write failures problem" (and rightly so, because there isn't
such a problem). The fact that malloc is called a lot is not an excuse for
calling it badly.
Memory is subtly different from other resources.

Let's say there arises a requirement to find the shortest path through a
maze. We are not sure whether this is computable in reasonable time or not,
but we are confident enough to commit to writing a function that finds "a
short path" and executes in reasonable time.
Since we don't have the function, we can define an interface. Then we work
out the shortest path for a few test cases by hand, and we've got a plugin
that works on the test cases, and gives the developers of the rest of the
program something to play with.

Now does our algorithm require dynamic memory or not? Can it return an out
of memory fail condition?
What about the callers of the function. Can they return OOM fail conditions
or not?
Maybe we'd better say that the algorithm does use dynamic memory, even if at
the end of the day it does not, just to be on the safe side.

Memory is different from all other resources.
--
Free games and programming goodies.
http://www.personal.leeds.ac.uk/~bgy1mm

Feb 8 '08 #122
On Fri, 8 Feb 2008 13:31:24 -0600, Ed Jensen wrote
(in article <13*************@corp.supernews.com>):
Randy Howard <ra*********@fooverizonbar.netwrote:
>Just give them time. It won't be long before someone argues that
checking return values fopen() is impossible to do correctly, so don't
even try.

It's sad to see this thread continue to include so many childish
insults.
Who did I insult?

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

Feb 8 '08 #123
Richard Tobin wrote:
In article <00*****************************@news.verizon.net> ,
Randy Howard <ra*********@FOOverizonBAR.netwrote:
>Just give them time. It won't be long before someone argues that
checking return values fopen() is impossible to do correctly, so don't
even try.

But in fact fopen() failure is far more likely to be due to user error
(notably, typing in the wrong file name), and thus more likely to be
recoverable.
But it could be due to the system not being able to allocate memory for
buffers. Wait a minute, wasn't there a recent thread about allocation
failures?

--
Ian Collins.
Feb 8 '08 #124

"Ian Collins" <ia******@hotmail.comwrote in message
As I said before, it's very hard and therefore error prone to write
exception safe code with the mechanisms C provides for all of the
reasons it's very hard to use multiple points of return. Square that
when exceptions can escape out of functions.
I'd agree here.
Exceptions simplify the callee at the expense of more work in the caller. In
fact they often make the interfaces too difficult to use.
However if you have a chain of out-of-memory returns you are effectively
handcoding the C++ excpetion mechanism, so you lose the syntaxtical
conveneience as well.

--
Free games and programming goodies.
http://www.personal.leeds.ac.uk/~bgy1mm
Feb 8 '08 #125
In article <61**************@mid.individual.net>,
Ian Collins <ia******@hotmail.comwrote:
>>Just give them time. It won't be long before someone argues that
checking return values fopen() is impossible to do correctly, so don't
even try.
>But in fact fopen() failure is far more likely to be due to user error
(notably, typing in the wrong file name), and thus more likely to be
recoverable.
>But it could be due to the system not being able to allocate memory for
buffers. Wait a minute, wasn't there a recent thread about allocation
failures?
Perhaps I should have been more explicit.

There is a greater return on programming effort in trying to recover
from fopen() failures than malloc() failures.

The fact that fopen() could fail because malloc() fails does not
change that.

-- Richard
--
:wq
Feb 8 '08 #126
Malcolm McLean wrote:
>
I'd agree here.
Exceptions simplify the callee at the expense of more work in the
caller. In fact they often make the interfaces too difficult to use.
However if you have a chain of out-of-memory returns you are effectively
handcoding the C++ excpetion mechanism, so you lose the syntaxtical
conveneience as well.
That's why compile-time exception checking is needed in C++ too, but
this is completely off topic here.

Feb 8 '08 #127
On Fri, 08 Feb 2008 22:48:39 GMT, Randy Howard
<ra*********@FOOverizonBAR.netwrote:
>On Fri, 8 Feb 2008 13:31:24 -0600, Ed Jensen wrote
(in article <13*************@corp.supernews.com>):
>Randy Howard <ra*********@fooverizonbar.netwrote:
>>Just give them time. It won't be long before someone argues that
checking return values fopen() is impossible to do correctly, so don't
even try.

It's sad to see this thread continue to include so many childish
insults.

Who did I insult?
Me. You insulted me. I expect your apology by certified mail.
:-)

More seriously, you are corrupting the dialog with a strawman.
Richard Harter, cr*@tiac.net
http://home.tiac.net/~cri, http://www.varinoma.com
Save the Earth now!!
It's the only planet with chocolate.
Feb 9 '08 #128
On Feb 8, 3:56 pm, Richard Heathfield <r...@see.sig.invalidwrote:
ymunt...@gmail.com said:
On Feb 8, 12:51 pm, Richard Heathfield <r...@see.sig.invalidwrote:

<snip>
A generic routine such as fgetline can't reasonably decide
what to do on allocation failure, so it has only two options - crash and
burn, or tell the caller. Crash-and-burn would be stupid, so we tell the
caller.
fgetline() returns an error, yes. What does it caller do?
The caller thinks it hit EOF (that's my hypothesis).

Oh, I see - fair enough. Yes, the test is against 0, and doesn't handle
malloc failure separately. It ought to. That's a weakness in the program
(not the library), which I ought to remedy. In fact, I was just looking
over the code again, and spotted it's not the only way in which emgen
needs fixing. When I get some time, I'll do something about that.
Oh, and to make sure I'm in your killfile again: fix your code
then talk about incompetence of others.

I don't see why you think a reasonable complaint about my shoddy code would
land you in my killfile. As for "the incompetence of others", incompetence
can be rooted in either (or both) of two problems - ignorance (not having
learned yet) or stupidity (refusing to put into practice the things one
ought to have learned). Ignorance is correctable (or corrigible, perhaps)
and forgivable. Stupidity is harder to correct and less forgivable.
Unfortunately for me, the emgen code shows definite signs of stupidity on
my part - so yes, I ought to go fix that code.

But when I do so, I will fix it to deal with allocation failures properly -
"crash and burn" should be a last resort, not a first response.
So you proved that your talking about checking malloc() failure,
"easy" if(pm != NULL) and stuff is just that: talking. Perhaps
you got wiser and better after you have written that code.
Or perhaps it was written by RH-human, who doesn't bother to check
return of fwrite or fclose (something that can actually happen,
unlike malloc() failure right after main() start), and who checks
malloc() result out of habit without any serious thinking about
what should be done in case of actual error; and the talking here
is done by RH-Teh-Good-Programmer. I suspect it's the latter.

So please, just let people who suck in writing bug-free programs
talk about ways to have less bugs. You know, let those who does
not pretend he is Good, talk about how to write better programs.
Without your wise comments about something easy to type.

Yevgen

P.S. Written using groups.google.com. May I please get back
into your killfile?
Feb 9 '08 #129
ym******@gmail.com said:
On Feb 8, 3:56 pm, Richard Heathfield <r...@see.sig.invalidwrote:
<snip>
>But when I do so, I will fix it to deal with allocation failures
properly - "crash and burn" should be a last resort, not a first
response.

So you proved that your talking about checking malloc() failure,
"easy" if(pm != NULL) and stuff is just that: talking.
Wrong. Such failures *are* checked. I have accepted that they are checked
in a suboptimal manner and that the handling could be improved, and I will
do so when I get some time to do that. But *some* checking is better than
*none*. It has been claimed that it is *impossible* to check all
allocation requests. The fact that you've found some checking which could
be done better does not mean you've found an absence of checking.
Or perhaps it was written by RH-human, who doesn't bother to check
return of fwrite or fclose (something that can actually happen,
Right, I should check fclose too. Well spotted.

unlike malloc() failure right after main() start),
No, that can happen too. You keep oscillating between right and wrong,
almost as if you were human or something.
May I please get back into your killfile?
What I read is up to me. What you read is up to you. If you don't like what
you read, it's your job to change your killfile, not my job to change
mine.

--
Richard Heathfield <http://www.cpax.org.uk>
Email: -http://www. +rjh@
Google users: <http://www.cpax.org.uk/prg/writings/googly.php>
"Usenet is a strange place" - dmr 29 July 1999
Feb 9 '08 #130

"Richard Heathfield" <rj*@see.sig.invalidwrote in message
ym******@gmail.com said:

>unlike malloc() failure right after main() start),

No, that can happen too. You keep oscillating between right and wrong,
almost as if you were human or something.
Isn't there some guarantee that a hosted program will have 64K of heap
space? Or is it just a figment of my imagination?

--
Free games and programming goodies.
http://www.personal.leeds.ac.uk/~bgy1mm

Feb 9 '08 #131

"Ian Collins" <ia******@hotmail.comwrote in message
Richard Tobin wrote:
>But in fact fopen() failure is far more likely to be due to user error
(notably, typing in the wrong file name), and thus more likely to be
recoverable.
But it could be due to the system not being able to allocate memory for
buffers. Wait a minute, wasn't there a recent thread about allocation
failures?
It could be, but it won't be. I frequently have fopen() fail on me. Every
single time it has been due to the path being wrong, never to memory
exhaustion.

--
Free games and programming goodies.
http://www.personal.leeds.ac.uk/~bgy1mm

Feb 9 '08 #132
Malcolm McLean said:
>
"Richard Heathfield" <rj*@see.sig.invalidwrote in message
>ym******@gmail.com said:

>>unlike malloc() failure right after main() start),

No, that can happen too. You keep oscillating between right and wrong,
almost as if you were human or something.
Isn't there some guarantee that a hosted program will have 64K of heap
space? Or is it just a figment of my imagination?
It's a figment, but it has a basis in reality. C90 guarantees that you can
construct at least one object at least 32767 bytes in size. (C99 increases
that to 65535 bytes.) C doesn't define a "heap", though.

--
Richard Heathfield <http://www.cpax.org.uk>
Email: -http://www. +rjh@
Google users: <http://www.cpax.org.uk/prg/writings/googly.php>
"Usenet is a strange place" - dmr 29 July 1999
Feb 9 '08 #133
[snips]

On Sat, 09 Feb 2008 17:13:55 -0800, Keith Thompson wrote:
So you're saying that this program:

#include <stdio.h>
#include <stdlib.h>
int main(void)
{
#define SIZE (1024L & 1024L)
void *p = malloc(SIZE);
if (p == NULL) {
return 0;
}
free(p);
p = malloc(SIZE);
if (p == NULL) {
puts("OOPS!\n");
}
free(p);
return 0;
}

cannot legally print "OOPS!"?

Of course it can - but *not* through failure to reserve that initial
block of memory for subsequent reallocation.

It could, for example, simply have a bug which fails to put the memory
back into the allocation area properly, which would cause a failure, but
it *cannot*, within the confines of the standard, fail on the second
malloc because the OS has taken over the memory; this is *expressly*
disallowed by the definition of free.
Consider an implementation in which malloc and free maintain some kind
of internal history, not accessible to the program but available for
debugging. The state of the "heap" (or whatever the implementation
uses) could easily be different after the first malloc/free pair than it
was at the beginning of the program.
Indeed. The second malloc can fail, no argument. It simply cannot fail
*because free returned the memory back to the OS*. The definition of
free, in the context in which it is applied, doesn't permit that.

Feb 10 '08 #134
Kelsey Bjarnason <kb********@gmail.comwrites:
[snips]
On Sat, 09 Feb 2008 17:13:55 -0800, Keith Thompson wrote:
>So you're saying that this program:

#include <stdio.h>
#include <stdlib.h>
int main(void)
{
#define SIZE (1024L & 1024L)
void *p = malloc(SIZE);
if (p == NULL) {
return 0;
}
free(p);
p = malloc(SIZE);
if (p == NULL) {
puts("OOPS!\n");
}
free(p);
return 0;
}

cannot legally print "OOPS!"?

Of course it can - but *not* through failure to reserve that initial
block of memory for subsequent reallocation.

It could, for example, simply have a bug which fails to put the memory
back into the allocation area properly, which would cause a failure, but
it *cannot*, within the confines of the standard, fail on the second
malloc because the OS has taken over the memory; this is *expressly*
disallowed by the definition of free.
>Consider an implementation in which malloc and free maintain some kind
of internal history, not accessible to the program but available for
debugging. The state of the "heap" (or whatever the implementation
uses) could easily be different after the first malloc/free pair than it
was at the beginning of the program.

Indeed. The second malloc can fail, no argument. It simply cannot fail
*because free returned the memory back to the OS*. The definition of
free, in the context in which it is applied, doesn't permit that.
I see an ambiguity in the standard's wording that you apparently don't
see (which isn't necessarily to say that I'm right and you're wrong).

The standard barely, if at all, acknowledges the possibility of other
programs executing in parallel. But it certainly doesn't forbid them.
The existence of the system() function clearly implies that, at least,
another program can execute while the current one is suspended.

The free() function "causes the space pointed to by ptr to be
deallocated, that is, made available for further allocation". It
doesn't explicitly say by whom or by what, and it's not nearly as
obvious to me as it seems to be to you that it must be available to
the current program. If I malloc() a chunk of memory, then free() it,
it doesn't seem entirely unreasonable for that space to be made
available to a program that I then invoke via system(). (But then you
could argue, I suppose, that that space must be deallocated when the
other program terminates, and made available again to the current
program.)

If my program needs a huge amount of memory during startup, but I know
it will never need it again as it continues to run, I *want* to be
able to return it to the OS rather than hogging it indefinitely.

The real question is what the authors of the standard intended, which
is why I've posted the question to comp.std.c; see the thread
"available for further allocation"?

--
Keith Thompson (The_Other_Keith) <ks***@mib.org>
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
Feb 10 '08 #135
Ian Collins wrote, On 08/02/08 19:23:
Ed Jensen wrote:
>Ian Collins <ia******@hotmail.comwrote:
>>char* p0 = malloc(100);
char* p1 = malloc(200);
char* p2 = malloc(300);

What do you do if the second malloc throws?
In my C code, I typically use a pattern something like this:

int ReturnValue = SUCCESS;
char *p0 = NULL;
char *p1 = NULL;
char *p2 = NULL;
char *p3 = NULL;
>if ((p0 = malloc(100)) == NULL)
{
ReturnValue = ENOMEM;
goto ExitFunction;
}
But what if you acquire something here...
if ((p3 = malloc(100)) == NULL
{
ReturnCalue = ENOMEM;
goto ExitFunction;
}
>if ((p1 = malloc(200)) == NULL)
{
ReturnValue = ENOMEM;
goto ExitFunction;
}
and release it here?
free(p3);
p3 = NULL;
>if ((p2 = malloc(300)) == NULL)
{
ReturnValue = ENOMEM;
goto ExitFunction;
}

/* Do some work with the allocated memory */

ExitFunction:

free(p0);
free(p1);
free(p2);
free(p3);
>return ReturnValue;
There, that wasn't difficult.
--
Flash Gordon
Feb 10 '08 #136
In article <qe************@spanky.localhost.net>,
Kelsey Bjarnason <kb********@gmail.comwrote:
>Indeed. The second malloc can fail, no argument. It simply cannot fail
*because free returned the memory back to the OS*. The definition of
free, in the context in which it is applied, doesn't permit that.
As I pointed out before, since there is no way for the program to
tell why it failed, it must be allowed under the as-if rule.

A program where malloc() fails because it has returned memory to
the OS behaves as if it failed for some other reason.

-- Richard
--
:wq
Feb 10 '08 #137
Flash Gordon wrote:
Ian Collins wrote, On 08/02/08 19:23:
>Ed Jensen wrote:
>>Ian Collins <ia******@hotmail.comwrote:
char* p0 = malloc(100);
char* p1 = malloc(200);
char* p2 = malloc(300);

What do you do if the second malloc throws?
In my C code, I typically use a pattern something like this:

int ReturnValue = SUCCESS;
char *p0 = NULL;
char *p1 = NULL;
char *p2 = NULL;

char *p3 = NULL;
>>if ((p0 = malloc(100)) == NULL)
{
ReturnValue = ENOMEM;
goto ExitFunction;
}
But what if you acquire something here...

if ((p3 = malloc(100)) == NULL
{
ReturnCalue = ENOMEM;
goto ExitFunction;
}
>>if ((p1 = malloc(200)) == NULL)
{
ReturnValue = ENOMEM;
goto ExitFunction;
}
and release it here?

free(p3);
p3 = NULL;
I intended the "something" to be something other than memory, say a lock
or opening a file.
>
There, that wasn't difficult.
Not difficult, but oh so messy!

Try again with "something" being a file!

--
Ian Collins.
Feb 11 '08 #138
Richard Heathfield schrieb:
ym******@gmail.com said:
>>A bonus question: what happens when malloc() fails inside fgetline()
(my hypothesis: nothing, we pretend we hit EOF. But we don't "crash
and burn", which is Good)


Your hypothesis is incorrect; fgetline returns a non-zero error code for an
allocation failure (it happens to be -3, which I really ought to wrap in a
#define).
why not specific POSIX.1 [-] ENOMEM
(happens to be 12 here)

Wolfgang
Feb 11 '08 #139
Wolfgang Riedel said:
Richard Heathfield schrieb:
>ym******@gmail.com said:
>>>A bonus question: what happens when malloc() fails inside fgetline()
(my hypothesis: nothing, we pretend we hit EOF. But we don't "crash
and burn", which is Good)


Your hypothesis is incorrect; fgetline returns a non-zero error code for
an allocation failure (it happens to be -3, which I really ought to wrap
in a
#define).

why not specific POSIX.1 [-] ENOMEM
Because under ISO C it's not guaranteed to be present (in which case the
code won't compile unless I define it myself, in which case I invade
implementation namespace).

--
Richard Heathfield <http://www.cpax.org.uk>
Email: -http://www. +rjh@
Google users: <http://www.cpax.org.uk/prg/writings/googly.php>
"Usenet is a strange place" - dmr 29 July 1999
Feb 11 '08 #140
Richard Heathfield wrote:
Wolfgang Riedel said:
>Richard Heathfield schrieb:
>>ym******@gmail.com said:
A bonus question: what happens when malloc() fails inside
fgetline() (my hypothesis: nothing, we pretend we hit EOF. But we
don't "crash and burn", which is Good)
Your hypothesis is incorrect; fgetline returns a non-zero error
code for an allocation failure (it happens to be -3, which I really
ought to wrap in a
#define).

why not specific POSIX.1 [-] ENOMEM

Because under ISO C it's not guaranteed to be present (in which case
the code won't compile unless I define it myself, in which case I
invade implementation namespace).
#include <errno.h>
#ifndef ENOMEM
# define ENOMEM 12
#endif

And no namespace invasion takes place, does it?

Bye, Jojo
Feb 11 '08 #141
In article <fo**********@online.de>,
Joachim Schmitz <jo**@schmitz-digital.dewrote:
>#include <errno.h>
#ifndef ENOMEM
# define ENOMEM 12
#endif
What if errno.h contains

#ifdef _SOME_EXTENSION
#define ENOMEM 13
#endif

and the user does

#include "whatever_defines_getline"
#define _SOME_EXTENSION
#include <errno.h>

That is, can you guarantee ESOMETHING isn't going to be defined just
by including <errno.hand doing an #ifdef?

-- Richard
--
:wq
Feb 11 '08 #142
Ian Collins wrote, On 11/02/08 03:57:
Flash Gordon wrote:
>Ian Collins wrote, On 08/02/08 19:23:
>>Ed Jensen wrote:
Ian Collins <ia******@hotmail.comwrote:
char* p0 = malloc(100);
char* p1 = malloc(200);
char* p2 = malloc(300);
>
What do you do if the second malloc throws?
In my C code, I typically use a pattern something like this:

int ReturnValue = SUCCESS;
char *p0 = NULL;
char *p1 = NULL;
char *p2 = NULL;
char *p3 = NULL;
FILE *f1 = NULL;
>>>if ((p0 = malloc(100)) == NULL)
{
ReturnValue = ENOMEM;
goto ExitFunction;
}

But what if you acquire something here...
if ((p3 = malloc(100)) == NULL
{
ReturnCalue = ENOMEM;
goto ExitFunction;
}
if ((f1 = fopen("fred","r")) == NULL)
{
ReternValue = FILEERROR;
goto ExitFunction;
}

>>>if ((p1 = malloc(200)) == NULL)
{
ReturnValue = ENOMEM;
goto ExitFunction;
}

and release it here?
free(p3);
p3 = NULL;
fclose(f1);
f1 = NULL;
I intended the "something" to be something other than memory, say a lock
or opening a file.
>There, that wasn't difficult.

Not difficult, but oh so messy!

Try again with "something" being a file!
Just as easy. The same principle would work for a lock (your lock
function surely has a way of flagging that the lock was not granted). If
really necessary you can add a flag to indicate whether you have the
resource, but generally I find that this is not required.

As to messy, well, you can wrap it up in various ways to hide the mess
if you consider it messy.
--
Flash Gordon
Feb 11 '08 #143
Kelsey Bjarnason wrote:
[snips]

On Sat, 09 Feb 2008 17:13:55 -0800, Keith Thompson wrote:
>So you're saying that this program:

#include <stdio.h>
#include <stdlib.h>
int main(void)
{
#define SIZE (1024L & 1024L)
void *p = malloc(SIZE);
if (p == NULL) {
return 0;
}
free(p);
p = malloc(SIZE);
if (p == NULL) {
puts("OOPS!\n");
}
free(p);
return 0;
}

cannot legally print "OOPS!"?


Of course it can - but *not* through failure to reserve that initial
block of memory for subsequent reallocation.

It could, for example, simply have a bug which fails to put the memory
back into the allocation area properly, which would cause a failure, but
it *cannot*, within the confines of the standard, fail on the second
malloc because the OS has taken over the memory; this is *expressly*
disallowed by the definition of free.
Since malloc() is not obliged to describe the reason for a
failure, how could a program detect that the failure was or was
not due to "the OS has taken over the memory?" It seems to me
your contention is untestable, hence of no practical force.

As for "expressly disallowed," I see no language that refers
to the O/S taking over memory.

--
Er*********@sun.com
Feb 11 '08 #144
In article <7f************@spanky.localhost.net>,
Kelsey Bjarnason <kb********@gmail.comwrote:
>Under the terms of the standard, the memory released by free is available
to the application; the OS is not allowed to poach it.
I haven't yet seen anyone else who agrees with your interpretation of
this.
>So what happens if the malloc *does* fail? It means that the
implementation's memory management is *so* bad, it imposes a 50,000+ byte
overhead on a 10,000 byte allocation - a bug so bad as to be, IMO, fatal.
>So yes, under the as-if rule, you're right, the program cannot tell the
difference between a fatal implementation bug and non-conforming
behaviour... but then, does this matter? Whether it's a bug in the
memory management or a failure to reserve the memory as required, it is
*still* a conformance failure, a bug. Equivalence of failures under as-
if is, indeed, equivalence, but when both behaviours are broken, so what?
Is "impos[ing] a 50,000+ byte overhead on a 10,000 byte allocation" a
conformance failure rather than very poor quality of implementation?
Chapter and verse please. If it isn't a conformance failure, then nor
is releasing memory to the OS.

-- Richard
--
:wq
Feb 12 '08 #145
Kelsey Bjarnason wrote:
So we come to free. Free, which is defined, in part, as making
previously allocated memory available for further allocation. What does
this tell us?

Context, always context. Is the context of the C standard sufficient to
define the behaviour of the underlying OS? Or to even require an
underlying OS? No. Is it sufficient to define all the mechanics of how
the system manages its memory? No.

It *is*, however, sufficient to define what the C program can expect, and
it does so, right there. In defining the behaviour of free in the only
context which it *can* define things - that of the program - it expressly
says the memory will be made available for further allocation.

It has thus *guaranteed* this memory *will* be available. The OS cannot
poach it, this is expressly against what free guarantees.
There is no such guarantee - [7.20.3] states that "If the space
cannot be allocated, a null pointer is returned."

The C program can expect to receive either a pointer to the
requested allocation on success, or NULL on failure. /That/ is
what the standard guarantees.

--
Morris Dovey
DeSoto Solar
DeSoto, Iowa USA
http://www.iedu.com/DeSoto
Feb 12 '08 #146
On Mon, 11 Feb 2008 13:15:19 -0600, Kelsey Bjarnason wrote
(in article <7f************@spanky.localhost.net>):
[snips]

On Sun, 10 Feb 2008 23:26:29 +0000, Richard Tobin wrote:
>As I pointed out before, since there is no way for the program to tell
why it failed, it must be allowed under the as-if rule.

A program where malloc() fails because it has returned memory to the OS
behaves as if it failed for some other reason.

Actually, that's not applicable, strictly speaking.

Under the terms of the standard, the memory released by free is available
to the application; the OS is not allowed to poach it. Thus the
application can, in fact, rely on that memory being there.
Is this really a guarantee from the standard? I don't recall ever
reading such a guarantee, but I might have overlooked it. C&V please?
--
Randy Howard (2reply remove FOOBAR)
"The power of accurate observation is called cynicism by those
who have not got it." - George Bernard Shaw

Feb 12 '08 #147
On Tue, 12 Feb 2008 00:42:06 -0600, Richard Heathfield wrote
(in article <uq******************************@bt.com>):
Randy Howard said:
>On Mon, 11 Feb 2008 13:15:19 -0600, Kelsey Bjarnason wrote
(in article <7f************@spanky.localhost.net>):
<snip>
>>Under the terms of the standard, the memory released by free is
available
to the application; the OS is not allowed to poach it. Thus the
application can, in fact, rely on that memory being there.

Is this really a guarantee from the standard? I don't recall ever
reading such a guarantee, but I might have overlooked it. C&V please?

Kelsey's text is of course from the description of free():

"The free function causes the space pointed to by ptr to be
deallocated, that is, made available for further allocation."

What is at issue here is not C&V, but the interpretation thereof.
Quite. If it said "for further allocation by the same program" maybe.
As is, I'm not sure I agree.
--
Randy Howard (2reply remove FOOBAR)
"The power of accurate observation is called cynicism by those
who have not got it." - George Bernard Shaw

Feb 12 '08 #148
In article <mm************@spanky.localhost.net>,
Kelsey Bjarnason <kb********@gmail.comwrote:
>>>Under the terms of the standard, the memory released by free is
available to the application; the OS is not allowed to poach it.
>I haven't yet seen anyone else who agrees with your interpretation of
this.
>Can you find anything in the standard which *allows* this behaviour?
The difference in interpretation is that you're the only one who thinks
the standard would have to explicitly allow it.
>So we come to free. Free, which is defined, in part, as making
previously allocated memory available for further allocation. What does
this tell us?

Context, always context. Is the context of the C standard sufficient to
define the behaviour of the underlying OS? Or to even require an
underlying OS? No. Is it sufficient to define all the mechanics of how
the system manages its memory? No.

It *is*, however, sufficient to define what the C program can expect, and
it does so, right there. In defining the behaviour of free in the only
context which it *can* define things - that of the program - it expressly
says the memory will be made available for further allocation.
Again, you're the only one who interprets it that way.

As you say, the standard can't be expected to define the details
of the operating system. If it can't do that, and it can't prevent
memory being returned to the operating system without talking
explicitly about the operating system, you are led to the absurd
conclusion that a programming language standard *can't* allow
memory to be return to the operating system.
>So someone brings up the as-if rule, to wit, the implementation can
behave "as-if" the OS stole the memory.
No, that's not what I said. It can return it to the operating system
because that is behaving as if malloc() failed for some other (allowable)
reason.
>So, if the as-if rule doesn't apply, what's left? Under what other
conditions can an allocation request fail, despite the guarantees of the
memory being available?
>2) Your implementation's memory management is so bad that when it has a
pool of 60,000 bytes available it can't manage the memory pool well
enough to actually hand back 10,000 bytes worth - your implementation has
a serious, possibly fatal bug

3) Your implementation's memory management is so bad that it imposes an
overhead of more than 50,000 bytes on a 10,000 byte allocation, so the
allocation plus overhead won't fit in the 60,000 byte space available -
your implementation has a serious, possibly fatal bug
So is either of these "possibly fatal bugs" a conformance failure?
If so, which bit of the standard do they not conform to?
>Why is any of this even a discussion point, though? It's pretty cut and
dried; the definition of free says the memory is made available for
further allocation, the whole point to the standard is to define the
behaviour of the program, and it does so - it tells it, flat out, no ifs,
ands or buts, *no options whatsoever*, the memory is made available for
further allocations.
And the obvious interpretation, corresponding to reality, is that
these allocations may be under the control of the operating system.

There are three possibilities:

(1) The standard means, and is intended to mean, what you believe.
(2) The standard means what you believe, but this is due to poor
wording, and does not reflect the intent of the authors.
(3) The standard doesn't mean what you think.

Which of (1) and (2) do you think it is?

-- Richard
--
:wq
Feb 12 '08 #149
Randy Howard said:
On Mon, 11 Feb 2008 13:15:19 -0600, Kelsey Bjarnason wrote
(in article <7f************@spanky.localhost.net>):
<snip>
>Under the terms of the standard, the memory released by free is
available
to the application; the OS is not allowed to poach it. Thus the
application can, in fact, rely on that memory being there.

Is this really a guarantee from the standard? I don't recall ever
reading such a guarantee, but I might have overlooked it. C&V please?
Kelsey's text is of course from the description of free():

"The free function causes the space pointed to by ptr to be
deallocated, that is, made available for further allocation."

What is at issue here is not C&V, but the interpretation thereof.

Kelsey makes the most convincing case I have ever read for implementations
being required to make freed memory available to the program. Richard
Tobin said that nobody else has posted a view that supports Kelsey, but
let us not forget that ISO C conformance is not a democratic process. It
doesn't matter how many people write void main programs - it doesn't make
void main right, does it? Well, if Kelsey is right, it doesn't matter how
many people disagree with him. But if he's wrong, he's wrong.

Personally, I think he's right. But of course I could be wrong about that.

--
Richard Heathfield <http://www.cpax.org.uk>
Email: -http://www. +rjh@
Google users: <http://www.cpax.org.uk/prg/writings/googly.php>
"Usenet is a strange place" - dmr 29 July 1999
Feb 12 '08 #150

This discussion thread is closed

Replies have been disabled for this discussion.

By using this site, you agree to our Privacy Policy and Terms of Use.