realloc: invalid next size and malloc: memory corruption (fast)

匿名 (未验证) 提交于 2019-12-03 00:57:01

问题:

I am doing an exercise for fun from K and R C programming book. The program is for finding the longest line from a set of lines entered by the user and then prints it.

Inputs:

This is a test  This is another long test  this is another long testthis is another long test 

Observation:

It runs fine for the first two inputs but fails for the larger string (3rd input)

Errors:

Error in `./longest': realloc(): invalid next size: 0x000000000246e010 *** Error in `./longest': malloc(): memory corruption (fast): 0x000000000246e030 *** 

My efforts:

I have been trying to debug this since 2 days (rubber duck debugging) but the logic seems fine. GDB points to the realloc call in the _getline function and shows a huge backtrace with glibc.so memory allocation calls at the top.

Here is what I have written (partially, some part is taken from the book directly):-

#include <stdio.h> #include <stdlib.h>  int MAXLINE =  10; int INCREMENT = 10;  char* line = NULL, *longest = NULL;  void _memcleanup(){     free(line);     free(longest);       }  void copy(char longest[], char line[]){     int i=0;     char* temp = realloc(longest,(MAXLINE)*sizeof(char));     if(temp == NULL){         printf("%s","Unable to allocate memory");         _memcleanup();         exit(1);     }     longest = temp;      while((longest[i] = line[i]) != '\0'){         ++i;     }     }  int _getline(char s[]){   int i,c;   for(i=0; ((c=getchar())!=EOF && c!='\n'); i++){     if(i == MAXLINE - 1){       char* temp = realloc(s,(MAXLINE + INCREMENT)*sizeof(char));       if(temp == NULL){         printf("%s","Unable to allocate memory");         _memcleanup();         exit(1);       }        s= temp;       MAXLINE += INCREMENT;     }     s[i] = c;   }    if(c == '\n'){       s[i++] = c;   }    s[i]= '\0';    return i; }   int main(){   int max=0, len;    line = malloc(MAXLINE*sizeof(char));   longest = malloc(MAXLINE*sizeof(char));    while((len = _getline(line)) > 0){     printf("%d%d", len, MAXLINE);     if(len > max){       max = len;       copy(longest, line);     }   }   if(max>0){     printf("%s",longest);   }    _memcleanup();   return 0; } 

回答1:


A parameter in C is a copy of the original value everytime; in case of
a pointer it will point to the same location but the address itself is copied.

realloc resizes the buffer asociated with the address, everything fine so far.
But it can relocate the whole thing and assign a completely new address,
and this new address (if it happens) will be lost after the function returns to main.

Use a double pointer:
Pass a char **s instead of char *s (==char s[]) as formal parameter,
pass &xyz intead of xyz as actual value, and inside the function,
use *xyz and **xyz (or (*xyz)[index]) for address and value.

Other things:
Global variables are ugly (and confusing when named same as parameters),
multiplying with sizeof(char)
and names in capitals should be used for #define



回答2:

The double pointer alone, isn't the solution to your problems. You have 2 primary issues. You can see them by entering your strings as a string of characters and will notice you problem occurs when you pass the 20th character. (e.g. 01234567890123456789)

You have declared both line and longest globally. So while you can rewrite _getline (char **s), you can also simply update line at the end of _getline with memcpy (include string.h). For example:

    memcpy (line, s, (size_t)i);      return i; } 

That cures your _getline issue. Issue two is fairly straight forward. You are not null-terminating longest in copy. (your choice of arguments with the same name as the globals presents challenges as well) Including the following fixes copy:

        ++i;     }      longest[i] = '\0'; } 

If you incorporate both changes, then I believe you will find you routine works. You can then rewite _getline (char **s) and pass &line as another exercise. For example, you can rewrite _getline as:

int _getline (char **s) {     int i, c;     for (i = 0; ((c = getchar ()) != EOF && c != '\n'); i++) {         if (i == MAXLINE - 1) {             char *temp = realloc (*s, (MAXLINE + INCREMENT) * sizeof (char));             if (temp == NULL) {                 printf ("%s", "Unable to allocate memory");                 _memcleanup ();                 exit (1);             }             *s = temp;             MAXLINE += INCREMENT;         }         (*s)[i] = c;     }      if (c == '\n') {         (*s)[i++] = c;     }      (*s)[i] = '\0';      return i; } 

And then modify your call in main to:

while ((len = _getline (&line)) > 0) { 


易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!