Re: malloc()/realloc() - have I got this right?



CBFalconer said:

<snip>

Here, without the documentation, .h file, test routines, etc. is
the actual (standard C) code for ggets.c. Instead of listening to
the mewling of people who don't like to see malloc called within a
routine,

....of whom I am not one...

read the code, and make your own decision.

Okay.

ggets is a macro in ggets.h that uses the FILE stdin.

Fair enough, although presumably you mean FILE *.


#include <stdio.h>
#include <stdlib.h>
#include "ggets.h"

#define INITSIZE 112 /* power of 2 minus 16, helps malloc */

MIGHT help malloc. It depends on the implementation.

#define DELTASIZE (INITSIZE + 16)

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?

int fggets(char* *ln, FILE *f)
{
int cursize, ch, ix;
char *buffer, *temp;

*ln = NULL; /* default */

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!

if (NULL == (buffer = malloc(INITSIZE))) return NOMEM;
cursize = INITSIZE;

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 fine if cursize starts with a value of at
least 10, which it does in this case).

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.

<snip>

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.

--
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
.



Relevant Pages

  • Re: malloc()/realloc() - have I got this right?
    ... Be aware, if you do so, that the above routine has what some people ... int cursize, ch, ix; ... char *buffer, *temp; ...
    (comp.lang.c)
  • Re: input word
    ... int cursize, ch, ix; ... char *buffer, *temp; ...
    (comp.lang.c)
  • Re: input word
    ... have adhered to this principle. ... int cursize, ch, ix; ... char *buffer, *temp; ... each section, the leading performer in a theatrical performance, ...
    (comp.lang.c)
  • Re: Reading a file...
    ... size_t curSize = BASE; ... Allocate the buffer at its initial size. ... while (moreData) ... fichero.c:59: warning: float format, double arg ...
    (comp.lang.c)