C - realloc error: corrupted size vs prev_size

20,448

size needs updating when inputch == '\n'.

char *tmp = realloc(str, sizeof(char) * length + 1 /* or no +1 */); can shrink the allocation. which makes a later if (length == size) invalid (the true allocation size is smaller) and so str[length++] = inputch; lost memory access protection. Update size to fix that hole.

+1 not needed - it simply hid the problem as the + 1 did not shrink the allocation as much.

  char *tmp = realloc(str, sizeof(char) * length);
  if (tmp == NULL) {
    exit(0);
  } else {
    str = tmp;
  }
  size = length; // add

Concerning sizeof(char)* code. The idea of scaling by the size of the target type is good, yet with char it is not important as it is always 1. @Lee Daniel Crocker

If code wants to reflect that the type of the target may change, do not use size(the_type), use sizeof(*the_pointer). Easier to code, review and maintain.

// Don't even need to code the type `str` points to
tmp = realloc(str, sizeof *str * length);
Share:
20,448
rhoward
Author by

rhoward

Updated on January 24, 2020

Comments

  • rhoward
    rhoward over 4 years

    Could someone please explain the error?
    I was getting the error until, on a whim, I changed the line from:

    char *tmp = realloc(str, sizeof(char)*length);
    // to                                           added 1
    char *tmp = realloc(str, sizeof(char) * length + 1);
    

    I thought that multiplying sizeof(char) by length would reallocate a new memory area of size=sizeof(char)*length. I'm not understanding why adding 1 fixes the problem.

        void edit_print(char *inputStr, size_t space_size) {
          size_t ch_position = 0;
          size_t space_column_count = 0;
          size_t num_spaces_left = 0;
          while ((inputStr[ch_position] != '\0')) {
            if ((inputStr[ch_position] == '\t') && (space_size !=0)) {
              num_spaces_left = (space_size-(space_column_count % space_size));
              if (ch_position == 0 || !(num_spaces_left)) {
                for (size_t i=1; i <= space_size; i++) {
                  putchar(' ');
                  space_column_count++;
                }
                ch_position++;
              } else {
                for (size_t i=1; i <= num_spaces_left; i++) {
                  putchar(' ');
                  space_column_count++;
                }
                ch_position++;
              }
            } else {
              putchar(inputStr[ch_position++]);
              space_column_count++;
            }
          }
          printf("\n");
        }
    
            int main(int argc, char *argv[]) {
              size_t space_size_arg = 3; 
              int inputch;
              size_t length = 0;
              size_t size = 10;
              char *str = realloc(NULL, sizeof(char) * size);
              printf("Enter stuff\n");
    
              while ((inputch = getchar()) != EOF) {
                if (inputch == '\n') {
                  str[length++] = '\0';
    
                  //changed line below
                  char *tmp = realloc(str, sizeof(char) * length + 1);
    
                  if (tmp == NULL) {
                    exit(0);
                  } else {
                    str = tmp;
                  }
                  edit_print(str, space_size_arg);
                  length = 0;
                } else {
                  str[length++] = inputch;
                  if (length == size) {
                    char *tmp = realloc(str, sizeof(char) * (size += 20));
                    if (tmp == NULL) {
                      exit(0);
                    } else {
                      str = tmp;
                    }
                  }
                }
              }
              free(str);
              return 0;
            }
    

    EDIT: the error message I original got was the one in the heading of this post. After making the changes suggested by chux, the error is "realloc(): invalid next size: *hexnumber**"

    • user4581301
      user4581301 over 6 years
      Recommend letting us in on "the error" Could be very helpful in figuring out what went wrong.
    • Igor Tandetnik
      Igor Tandetnik over 6 years
      My guess: edit_print contains a buffer overrun error. You masked this bug by giving it some extra room to overrun into.
    • chux - Reinstate Monica
      chux - Reinstate Monica over 6 years
      OT: This does not explain the error, yet sizeof(char) * length + 1 is semantically incorrect. The sizeof() should multiple by the sum of length + 1. But since, in this case, sizeof(char)==1 --> no problem.
    • Lee Daniel Crocker
      Lee Daniel Crocker over 6 years
      First of all, "sizeof(char)" is defined to be 1, so is irrelevant and superfluous everywhere. Then, the only code that seems to do anything with all this memory you're allocating is edit_print(), which you're not showing us.
    • rhoward
      rhoward over 6 years
      @LeeDanielCrocker I added the function
    • rhoward
      rhoward over 6 years
      @user4581301 the error is in the header. Thats all im getting.
    • chux - Reinstate Monica
      chux - Reinstate Monica over 6 years
      @rhoward207 Prior to each ... = realloc(ptr, sz);, add fprintf(stderr, "%d %p %zu\n", __LINE__, (void*)ptr, sz); and report the last output before code dies.
    • rhoward
      rhoward over 6 years
      @chux what is sz in the arguments?
    • chux - Reinstate Monica
      chux - Reinstate Monica over 6 years
      In realloc(NULL, sizeof(char) * size);, sz is sizeof(char) * size, In realloc(str, sizeof(char) * length + 1);, sz is sizeof(char) * length + 1. In realloc(str, sizeof(char) * (size += 20)); sz is sizeof(char) * (size + 20)); (not +=).
    • chux - Reinstate Monica
      chux - Reinstate Monica over 6 years
      General comment: A weak design attribute is testing the size after setting an element of the array. A better approach would test space availability first before str[length++] = inputch; and before str[length++] = '\0';
    • chux - Reinstate Monica
      chux - Reinstate Monica over 6 years
      Minor: if ((!*end) && num > 0) ---> if (options[2] != end && (!*end) && num > 0)
    • chux - Reinstate Monica
      chux - Reinstate Monica over 6 years
      Instead of including process_options() code. A MCVE would have used size_t space_size_arg = 3; - assuming that still fails. GTG
    • pm100
      pm100 over 6 years
      arent you allocated the buffer str for the next string on each loop. Are they all the same size? First time you have str = 10 bytes, then you count chars and realloc str to the size you just read. But that buffer is used fro the next string
  • rhoward
    rhoward over 6 years
    unfortunately your suggestion does not fix the error. I will edit my post to include what I am seeing. I also added edit_print. thank for the info about sizeof(type).
  • David C. Rankin
    David C. Rankin over 6 years
    Please provide a A Minimal, Complete, and Verifiable example for further help.
  • rhoward
    rhoward over 6 years
    @chux after adding fprintf, last few lines: ##### ####### ####### ###### # ####### ###### 100 0x55da9f4416a0 41 # # # # # # # # # # # # # 100 0x55da9f4416a0 41 # # # # # # # # # # # # 100 0x55da9f4416a0 44 *** Error in `./project1': corrupted size vs. prev_size: 0x000055da9f4416c0 *** Aborted (core dumped)
  • rhoward
    rhoward over 6 years
    fprintf(stderr, "%d %p %zu\n", LINE, (void*)str, sizeof(char)*length+1); @chux
  • chux - Reinstate Monica
    chux - Reinstate Monica over 6 years
    @rhoward207 Notice that the problem occurs on the first non-blank line shorter than prior ones. Certainly the issue is in shrinking the allocation. The 100 is suspicious as no line is longer than about 75 characters - hmmmm.