Haagenti
Haagenti

Reputation: 8144

Get line of FILE *

I'm trying to learn C (which is freaking hard...) so I wanted to write a routine which gets a line of a file. I created this function :

int c;
int buflen = 100;
if((*buffer = malloc(sizeof(char) * buflen)) == NULL) {
  DXLogWarn("Not enough memory");
  return;
}

char * dst = *buffer;
char * end = *buffer + buflen - 1;
while ((c = getc(fp)) != EOF) {
  if (c == '\n') {
    break;
  }
  if (dst < end) {
    *dst++ = c;
  }  
}
*dst = '\0';

Which works yay! But now I thought instead of cutting of the last part of the string I could realloc the buffer and continue till the '\n'. So I changed it to this:

void fget_line(FILE *fp, char **buffer) {
int c;
int buflen = 10;
if((*buffer = malloc(sizeof(char) * buflen)) == NULL) {
  DXLogWarn("Not enough memory");
  return;
}

char * dst = *buffer;
char * end = *buffer + buflen - 1;
while ((c = getc(fp)) != EOF) {
  if (c == '\n') {
    break;
  }

  if (dst < end) {
    *dst++ = c;
  } else {
    buflen *= 2;
    *buffer = realloc(*buffer, buflen * sizeof(char));
    if (*buffer == NULL) {
      DXLogError("Err");
      return;
    }
  }

}
*dst = '\0';
}

Which gives me an error : malloc: * error for object 0x10a8001b8: incorrect checksum for freed object - object was probably modified after being freed. * set a breakpoint in malloc_error_break to debug

Which I do not get. What am I doing wrong?

Upvotes: 0

Views: 146

Answers (1)

wimh
wimh

Reputation: 15232

at the start you do:

char * dst = *buffer;
char * end = *buffer + buflen - 1;

This set dst and end to the correct positions inside buffer. Then you reallocate buffer:

*buffer = realloc(*buffer, buflen * sizeof(char));

This causes buffer to get a new value which is probably different then before. So you also have to update dst and end to the new positions inside buffer.

Changing end is easy, but because you keep changing dst, it is difficult to calculate the new value. So instead of changing the pointers, it might be easier to store just the offset in a integer. Something like:

int pos=0;
while ((c = getc(fp)) != EOF) {
  if (c == '\n') {
    break;
  }

  if (pos >= buflen-1) {
    buflen *= 2;
    *buffer = realloc(*buffer, buflen * sizeof(char));
    if (*buffer == NULL) {
      DXLogError("Err");
      return;
    }
  }

  (*buffer)[pos] = c;
  pos++;
}
(*buffer)[pos] = '\0';

I also changed the if statement above, as you did not store the character which caused the reallocation.

Upvotes: 1

Related Questions