Re: calloc's, call by ref and function returning in C

From: goose (ruse_at_webmail.co.za)
Date: 10/12/04


Date: 12 Oct 2004 02:51:44 -0700

fade <dont_use_this_mail@mail.com> wrote in message news:<Xns957DC718EA9F8fadept@130.133.1.4>...
> Good afternoon!
>

Good morning :-)

> I need some guidence here on the best practice to make all
> the things work together (call by reference, function returning,
> memory allocation and freeing).
>
> To help me learn that, I'm trying to build a simple program
> that prints in the screen each line of a .txt file.
>
> #define BUFFERSIZE 3 /* for testing reallocation - should be bigger I
> know */
> int main(int argc, char *argv[])
> {
> int counter = 0;
> FILE* fin = NULL;
> char* buffer = (char*)calloc(BUFFERSIZE, 1);

You must check if buffer is NULL (i.e. if calloc
failed, you must handle the error).

> char* temp = NULL;
>
> if ( (fin = fopen("C:\\filein.txt", "r")) == NULL )
> {
> perror("Failed reading inputFile\n");
> exit(-1);

If you are going to return early, its best to
free up the memory you allocated with calloc above, no?

Also, I would get into the habit of ending a program
with return rather than exit.

> }
>
> while ( fgets(buffer, BUFFERSIZE, fin) != NULL )
> {
> /* Does buffer contain a whole line ended by \n ? */
> while (strchr(buffer, 10) == NULL)
> {
> /* Not a whole line. Read some more */
> temp = &buffer[strlen(buffer)];
> buffer = (char*)realloc(buffer, 2 * BUFFERSIZE);

What in case realloc returns NULL? In this case you are
clobbering buffer, so you can never free that memory again.
Also, temp might not be pointing at anything usefull after
the reallocation.

why not do it this way:
            temp = realloc (buffer, 2 * BUFFERSIZE);
            if (!temp) {
               /* ERROR */
               /* free all resources and return */
            }
            temp = &buffer[strlen(buffer)];

> if ( fgets(temp, BUFFERSIZE, fin) == NULL )
> {
> perror("Failed reading a full line\n");
> exit(-1);

Here again, you exit without freeing up resources.
Get into the habit of freeing up all resources you acquire.

> }
> }
> counter++;
> printf("Line %d = %s!\n", counter, buffer);
> }
>
> free(buffer);
> fclose(fin);
>
> /*system("PAUSE"); */
> getchar();
> return 0;
> }
>
>
> Well at this stage it works.

... with a little bit of luck, you mean :-)

> But if I want to make an auxiliary function for the line reading part,
> it won't run ok anymore.
>
> char* readLineFromFile(FILE* fileToRead, char* buffer, int bufferSize)
>
> If the user passes the buffer by reference to the function I can't
> determinate
> if buffer was declared as char* buffer = malloc(x) or
> char* buffer = char[x].
> I can't do a realloc of a char[100] I think. :^)
> Even if it is possible, when I return from this function
> the user would have to free the buffer.
> And I think that, if he had declared the buffer like
> char* buffer = char[x].
> he won't do a free because he wasn't expecting a realloc.
> So, a memory leak would occur, wouldn't it?
>
> Even if I declare the function this way
>
> char* readLineFromFile(FILE* fileToRead)
>
> I have to create the buffer inside it and I could reallocate,
> but then how would I free the buffer?
> If I free the buffer I can't return it. If I return it the function
> doesn't
> free the buffer allocated. :(
>
> How can I call this function from main and have free's in the right
> spot for every memory allocation made and still having the auxiliary
> function return each line?
>

Like this:

/*** warning; the following isn't tested ***/

char *read_line_from_file (FILE *infile) {
   static char *buffer = NULL;
   /* if we are called with NULL as input, then
      we must free all resources, in this case
      we free buffer if buffer was ever allocated
    */
   if (!infile) {
      if (buffer) {
         free (buffer);
      }
      return NULL;
   }
   /* this is where you put your code to read, allocate
      buffer (or reallocate, as the case may be) and
      populate buffer with the data from the file.
    */
   return buffer; /* you can always return NULL on error
                     or end of file.
                   */
}

#define FILENAME "filename.txt"

int main (void) {
   FILE *infile = fopen (FILENAME, "r");
   char *line = NULL;

   if (!infile) {
      fprintf (stderr, "cannot open file %s to read\n", FILENAME);
      return EXIT_FAILURE;
   }

   for (line = read_line_from_file (infile); /* line gets initialised */
        line!=NULL; /* loop ends if no line read */
        line = read_line_from_file (infile)) { /* line points to more data */
      printf ("line read is %s\n", line);
   }

   read_line_from_file (NULL); /* let function release all its resources */
   fclose (infile); /* release main's resources */
   return EXIT_SUCCESS;
}

hth,
   goose



Relevant Pages

  • Re: Alternative to C for system programming
    ... be blocks of memory that are GC and nonGC, ... to call it a systems programming language with GC. ... Just make sure your disk buffer or whatever is ... allocation of memory: I/O module thinks it will need more memory ...
    (comp.programming)
  • Re: Attention Windows Users
    ... > how there could be a buffer overflow. ... > memory. ... A "dynamic allocation" is one that occurs at run-time. ... a buffer overflow can occur with either a dynamic or static ...
    (rec.aviation.piloting)
  • Re: Variable-sized lines of text in linked list
    ... responsible for freeing the memory thus allocated. ... For memory allocation ... Freeing of assigned storage is the callers responsibility ...
    (comp.lang.c)
  • Re: return a string
    ... Declare a static array of char in your ... mallocmemory for the string inside your function ... >> provide a way to use an alternative allocation function. ... Pass an already allocated buffer and its size to your function. ...
    (comp.lang.c)
  • Re: Memory leak with socket BeginReceive?
    ... First, all allocation ... compact memory below the highest pinned object. ... socket.BeginReceive pins the buffer object that you pass in. ... The real fix is to allocate a fixed pool of buffers early during ...
    (microsoft.public.dotnet.framework)

Loading