Search code examples
cmallocrealloc

How do I fix realloc(): invalid next size in C


I have a Problem when I try to load a file into memory as an array.

I am trying to load a file into an array and print it out again but I would like to allow the memory to grow as the file length can be arbitrary.

When I run my Program locally on my Mac it seems to Work fine but when I try it on my Ubuntu VM, I get the following error realloc(): invalid next size
Aborted (core dumped)

My Code is as follows

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

char **loadfile(char *filename, int *len);
int main(int argc, char *argv[])
{

  if (argc == 1)
   {
    printf("Usage add file\n");
    return 1;

  }

  int length = 0;
  char **words = loadfile(argv[1],&length);

printf("%d\n", length);

for (int i = 0; i < length; i++) {
  printf("%s\n",words[i]);
}
printf("Done\n");

  return 0;
}

char **loadfile(char *filename, int *len)
{
const int STEPSIZE = 10;

  FILE *f = fopen(filename,"r");
  if (!f) {
    fprintf(stderr, "Can't open file\n");
    return NULL;
  }
  int arrlen = STEPSIZE;
   char **lines = (char **)malloc(STEPSIZE);
   char buf[100];
   int i = 0;
   int counter = 2;
   while (fgets(buf,100,f))
   {

     if (i == arrlen)
     {
        counter++;
       arrlen += STEPSIZE;
       char **newlines = (char **)realloc(lines,counter * STEPSIZE);
       if(!newlines)
       {
      printf("Out of memory\n");
      //return 2;
       }
       lines = newlines;
     }

    buf[strlen(buf)-1] = '\0';

    int slen = strlen(buf);

    char *str = (char *)malloc(slen + 1 *sizeof(char ));
    strcpy(str, buf);
    lines[i] = str;
    i++;
   }
   *len =i;
   return lines;
}

and for the life of me I cannot find the problem.

I can only assume the problem is somewhere in this section but I may be wrong:

 if (i == arrlen)
     {
        counter++;
       arrlen += STEPSIZE;
       char **newlines = (char **)realloc(lines,counter * STEPSIZE);
       if(!newlines)
       {
      printf("Out of memory\n");
      //return 2;
       }
       lines = newlines;
     }

Your Help is greatly appreciated


Solution

  • const int STEPSIZE = 10;

    char **lines = (char **)malloc(STEPSIZE);

    char **newlines = (char **)realloc(lines,counter * STEPSIZE);

    You don't want to allocate 10 bytes, but memory for 10 char * elements. Thus some subsequent access to lines[i] = str; is invalid.

    What you meant to do is:

    char **lines = malloc(sizeof(*lines) * STEPSIZE);
    char **newlines = realloc(lines, sizeof(*newlines) * counter * STEPSIZE);
    

    Alternatively you can use sizeof(char*).

    Also:

    char *str = (char *)malloc(slen + 1 *sizeof(char ));

    although it is correct and will work, because sizeof(char) is 1, but it's more clearly the intention was:

    char *str = malloc((slen + 1) * sizeof(char));
    

    Also, it's good to think if you should cast the result of malloc.