1
votes

I started learning about struct in C. Today I found a problem, that I can't solve. I have this code:

typedef struct fraze
{
  char *mostSearch = NULL; // for string from user
  double freq;
} s_FRAZE;

int readFraze( )
{
  int i = 2, k;
  size_t len = 0;
  char c;
  s_FRAZE *s;
  s = (s_FRAZE *)malloc( i * sizeof( int ));
  k = 0;
  while( (c = getchar()) != '\n')
  {
    ungetc( c, stdin );

    if( scanf( "%lf%c", &s[k].freq, &c) != 2 || c != ':' )
    {
      return 1;
    }

    if( k + 1 >= i )
    {
      i *= 2;
      printf("%d\n", i );
      s = (s_FRAZE *)realloc( s, i * sizeof( int ));
    }

    len = getline(&s[k].mostSearch, &len, stdin );
    s[k].mostSearch[len-1] = '\0';
    k++;
  }

  return 0;
}

I want to read while user don't type '\n', but it works 2x and then I get this erorr realloc(): invalid next size: 0x0000000001559010 *** I tryed use valgrind and there are more errors:

==7662== Invalid write of size 8
==7662== at 0x56AEBB4: _IO_vfscanf (vfscanf.c:2328)
==7662== by 0x56BBD3A: scanf (scanf.c:33)
==7662== by 0x40089F: readFraze() (main.c:31)
==7662== by 0x400818: main (main.c:15)
==7662== Address 0x59fe048 is 0 bytes after a block of size 8 alloc'd
==7662== at 0x4C27C0F: malloc (vg_replace_malloc.c:299)
==7662== by 0x400847: readFraze() (main.c:25)
==7662== by 0x400818: main (main.c:15)
==7662==
==7662== Conditional jump or move depends on uninitialised value(s)
==7662== at 0x56BFCA2: getdelim (iogetdelim.c:63)
==7662== by 0x40093E: readFraze() (main.c:44)
==7662== by 0x400818: main (main.c:15)

Can anyone tell me, what am I doing wrong?

1
Do not cast the result of malloc & friends in C.too honest for this site
malloc( i * sizeof( int )); --> malloc( i * sizeof( s_FRAZE )); assuming you want i elements in the array.Weather Vane
Same thing with realloc( s, i * sizeof( int )); --> realloc( s, i * sizeof( s_FRAZE ));Weather Vane
when calling malloc() and family of functions, always check (!=NULL) the returned value to assure the operation was successfuluser3629249
when compiling, always enable all the warnings, then fix those warnings. (for gcc, at a minimum use: -Wall -Wextra -pedantic ) The posted code not only raises numerous warnings, but also raises some errors. I.E. the posted code will NEVER run until all the errors are fixed. The only possibility, that I see, is this is not your real code. Please post the real codeuser3629249

1 Answers

5
votes

When you see a backtrace involving malloc, realloc or free, it means your heap is corrupted: your program overwrote some data structures used by the memory management system. The most common causes for that are writing past the bounds of a block allocated by malloc (buffer overflow) and continuing to use a memory block allocated by malloc after calling free on it (use after free).

As Weather Vane already mentioned in a comment, the size you pass to malloc and realloc for s doesn't match your usage of s. s is a pointer to an array of struct fraze, and you use elements up to k of this array, so the memory block must be large enough for k+1 elements of type struct fraze. Given your allocation policy, that means you must leave room for i elements of type struct fraze. But your actual allocation is for only sizeof( int ) bytes, which is not enough.

Make that

s = malloc(i * sizeof(*s));

and (with error checking)

s_FRAZE *new_s = realloc(s, i * sizeof(*s));
if (new_s == NULL) {
    fputs("Out of memory!\n", stderr);
    exit(2);
}
s = new_s;

Generally speaking, the size of an array of i elements that you're assigning the pointer s to is i * sizeof(*s). Don't use sizeof( TYPE)