0

I have some C code that contains an array of text that I'm trying to manipulate in the following manner :-

  • Allocate an array of pointers dictionary of size dictionary_size initialized to 50
  • Replace all spaces and \n's with '\0'
  • Store the address of every 3rd string(separated by an unknown number of \n's or spaces) in dictionary
  • If dictionary is full, realloc to size, dictionary_size * 2

The code however, causes the following error :-

*** glibc detected *** ./crack: realloc(): invalid next size: 0x0000000001386010 ***
^Cmake: *** [run] Interrupt

The code is as follows :-

 // Replace all spaces with '\0'
  for ( i = 0; i < file_size; i++ ) {
    if ( temp_buffer[i] == ' ' || temp_buffer[i] == '\n' ) {
      while ( temp_buffer[i] == ' ' || temp_buffer[i] == '\n' ) {
        temp_buffer[i] = '\0';
      }
      j++;
    }
    if ( (j-1) % 3 == 0 ) {
      dictionary[k] = temp_buffer+i;
      k += 1;
      if ( k == dictionary_size ) {
        dictionary_size *= 2;
        printf("Going to realloc to %d\n", dictionary_size);
        dictionary = (char **)realloc(dictionary, dictionary_size);
      }
    }
  }

[EDIT] Based on the debugging statements I have, the very first realloc(to a size of 100) fails.

  • There comes a point at which you can no longer double your allocation... apparently a 19G allocation is larger than your system can support. This is not as surprising as that you made it that far in your doubling to begin with. – mah Jan 14 '14 at 11:47
  • First, was `dictionary == NULL` or ever set based on a return from `malloc()`, or is `realloc()` the first thing you ever do? Second, _invalid next size: 0x0000000001386010_ suggests the size is not 100... have you confirmed at runtime that it's what you think it should be? – mah Jan 14 '14 at 11:52
  • The error indicates the program's memory management had been messed up. The term "*invalid next size: 0x0000000001386010*" does not refer to the size requested by `realloc()` but to an internally held value which is interpreted as an internal size of some management object and the size had been detected as being invalid. this is fatal. Check the program's memory allocation/freeing/access using a memchecker tool like Valgrind: http://valgrind.org – alk Jan 14 '14 at 12:00

2 Answers2

2

dictionary_size is the element (pointer) count, not the allocation size. should be dictionary_size * sizeof(char*)

dictionary = realloc(dictionary, dictionary_size * sizeof(*dictionary)); // safer, 10x @alk

Or (less recommneded):

dictionary = realloc(dictionary, dictionary_size * sizeof(char*));       // clearer

Also check that dictionary_size is properly initialized.

egur
  • 7,830
  • 2
  • 27
  • 47
  • Good catch - 1+! This backs my comment that the error messages given indicates an internal error in memory management, as due to allocating to few memory most probably unallocated memory had been overwritten. A eve nicer (and saver) correction would be to do: `dictionary = realloc(dictionary, dictionary_size * sizeof(*dictionary);` – alk Jan 14 '14 at 12:03
0

You are allocating too little memory. The error is caused by trashing the memory (and you can never know which error will actually come out from trashed memory).

If you allocate dictionary_size bytes you have room for dictionary_size/sizeof(char *) pointers.

Your if statement, instead, suggests that you think you have space for dictionary_size pointers, which is not the case.

Change your malloc/realloc to something like:

dictionary = (char **)realloc(dictionary, dictionary_size * sizeof(char *));

btw, you don't need to cast the return of realloc.

As a final suggestion, considering that realloc(NULL, ...) is equivalent to malloc(), it might be easier to write something like:

  dictionary = NULL;
...  other code here ...
  if ( k >= dictionary_size ) {
    while (k >= dictionary_size) dictionary_size *= 2;
    printf("Going to realloc to %d\n", dictionary_size);
    dictionary = (char **)realloc(dictionary, dictionary_size * sizeof(char *));
  }
  dictionary[k++] = temp_buffer+i;
... etc ...

So you are absolutely sure that whatever k is, you have enough room for dictionary[k].

Remo.D
  • 16,122
  • 6
  • 43
  • 74