Paul Manta
Paul Manta

Reputation: 31567

Reading line from file causes crash

I'm trying to read a line from a file character by character and place the characters in a string; here' my code:

char *str = "";
size_t len = 1; /* I also count the terminating character */

char temp;
while ((temp = getc(file)) != EOF)
{
    str = realloc(str, ++len * sizeof(char));
    str[len-2] = temp;
    str[len-1] = '\0';
}

The program crashes on the realloc line. If I move that line outside of the loop or comment it out, it doesn't crash. If I'm just reading the characters and then sending them to stdout, it all works fine (ie. the file is opened correctly). Where's the problem?

Upvotes: 1

Views: 91

Answers (3)

Sylvain Defresne
Sylvain Defresne

Reputation: 44463

Change your code to:

char *str = NULL; // realloc can be called with NULL
size_t len = 1; /* I also count the terminating character */

char temp;
while ((temp = getc(file)) != EOF)
{
    str = (char *)realloc(str, ++len * sizeof(char));
    str[len-2] = temp;
    str[len-1] = '\0';
}

Your issue is because you were calling realloc with a pointer to memory that was not allocated with either malloc or realloc which is not allowed.

From the realloc manpage:

realloc() changes the size of the memory block pointed to by ptr to size bytes.
          The contents will be unchanged to the minimum of  the  old  and  new
          sizes; newly allocated memory will be uninitialized.  If ptr is NULL,
          then the call is equivalent to malloc(size), for all values of size;
          if size is equal to zero, and ptr is not NULL, then the call is
          equivalent to free(ptr).  Unless ptr is NULL, it must have been
          returned by an earlier call  to malloc(), calloc() or realloc().  If
          the area pointed to was moved, a free(ptr) is done.

On a side note, you should really not grow the buffer one character at a time, but keep two counter, one for the buffer capacity, and one for the number of character used and only increase the buffer when it is full. Otherwise, your algorithm will have really poor performance.

Upvotes: 6

Kevin
Kevin

Reputation: 56049

You can't realloc a string literal. Also, reallocing every new char isn't a very efficient way of doing this. Look into getline, a gnu extension.

Upvotes: 2

Mark Ransom
Mark Ransom

Reputation: 308101

You can't realloc a pointer that wasn't generated with malloc in the first place.

You also have an off-by-one error that will give you some trouble.

Upvotes: 6

Related Questions