Re: malloc()/realloc() - have I got this right?
- From: Richard Heathfield <rjh@xxxxxxxxxxxxxxx>
- Date: Fri, 30 May 2008 11:03:53 +0000
CBFalconer said:
Richard Heathfield wrote:
CBFalconer said:... snip ...
enum {OK = 0, NOMEM};
Are those the only two failure conditions? What about end of file?
Or a stream error? Why not make it possible to report those?
You didn't read the whole routine. It also returns EOF, which is
not defined here. I did point out that this listing omitted the
documentation etc.
Your point is well-taken, although it does seem that you fail to
distinguish between genuine end-of-file and a stream error.
The problem with this approach, as I have explained before, is
that it doesn't allow the caller to re-use an existing buffer.
If they try, the above line leaks the previous memory!
In your opinion.
It is true that the claim that it is a problem is a matter of opinion. It
is not a matter of opinion, however, that an attempt to re-use an existing
buffer *will* leak memory.
Similarly, never use malloc to set a pre-existing
pointer variable. Buffer reuse would require additional
parameters, and user confusion. Avoided.
Yes, it would require additional parameters. User confusion can stem from
many sources, though: for example, "why is my program leaking like a
sieve?" or (for those who've worked this out, perhaps by reading the docs)
"why can't I re-use this perfectly good buffer?"
ix = 0;
while ((EOF != (ch = getc(f))) && ('\n' != ch)) {
if (ix >= (cursize - 1)) { /* extend buffer */
cursize += DELTASIZE;
The problem with this approach is that it doesn't scale well.
Remember that stdin doesn't necessarily mean keyboard input. The
input might, for example, be coming from a very, very fast fixed
disk. Consider changing to an exponential approach, e.g. cursize
*= 2; (or even cursize *= 1.1 or something like that, which is
fineat if cursize starts with a value of least 10, which it does
in this case).
Which it is not intended to.
I'm puzzled. Do you mean that it's not intended to scale well?
It will work for any size,
This suggests that it /is/ expected to scale well, which it fails to do.
but is
optimized for those sizes expected as interactive input.
I disagree. If input is interactive and therefore relatively thin, asking
for a multiple of the existing memory isn't going to cause a delay any
more noticeable than that suffered when asking for a fixed additional
amount. So in fact it's not (usefully) optimised for interactive input.
Rather, it's pessimised for non-interactive input.
Note that
the user can alter this part of the algorithm easily.
If by "user" you mean "programmer", yes, a reasonably skilled programmer
can do that quite easily. But why should he or she have to, when it's so
easy for the problem to be fixed at source?
if (NULL == (temp = realloc(buffer, (size_t)cursize))) {
The problem with this approach is that it runs a significant risk
of exhausting memory without the programmer having any control over
this. Consider accepting a parameter that specifies the largest
buffer size this call is allowed to allocate.
The point is to avoid the need for any extra parameters and
associated confusion.
I think you under-estimate the ability of computer programmers to deal with
what is, after all, a pretty simple interface even /with/ the extra
parameters.
These are genuine concerns. Your continued failure to address them
is, of course, entirely your decision, but I am at a loss to
understand how you can possibly recommend such a function (which you
do, continually) whilst these flaws remain.
Yes, similarly it is a great evil to have file open functions,
since failure to close them may cause data loss.
No, but it would be silly to have a function that, if passed a stream
pointer, immediately closes it just so that it can have the fun of opening
it again.
You are confusing faults with design objectives.
No, I'm saying that the design objective is flawed. For a very slight
change in the design, you can make the function considerably more useful,
but you choose not to do that.
All these points have been answered before,
To say, in effect, "tisn't" is not what I consider a sensible answer.
and you are perfectly free not to use ggets.
It is a freedom that I guard jealously, and I commend the same approach to
others until ggets is fixed to deal with the problems I've raised.
--
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
.
- Follow-Ups:
- Re: malloc()/realloc() - have I got this right?
- From: Keith Thompson
- Re: malloc()/realloc() - have I got this right?
- References:
- malloc()/realloc() - have I got this right?
- From: Dave
- Re: malloc()/realloc() - have I got this right?
- From: CBFalconer
- Re: malloc()/realloc() - have I got this right?
- From: Richard Heathfield
- Re: malloc()/realloc() - have I got this right?
- From: CBFalconer
- Re: malloc()/realloc() - have I got this right?
- From: Richard Heathfield
- Re: malloc()/realloc() - have I got this right?
- From: CBFalconer
- malloc()/realloc() - have I got this right?
- Prev by Date: Re: checking for close enough floating point values.
- Next by Date: Re: Four or Two Bytes?
- Previous by thread: Re: malloc()/realloc() - have I got this right?
- Next by thread: Re: malloc()/realloc() - have I got this right?
- Index(es):
Relevant Pages
|