【发布时间】:2014-08-26 21:00:26
【问题描述】:
我正在从 K 和 R C 编程书籍中做一个有趣的练习。该程序用于从用户输入的一组行中找到最长的行,然后将其打印出来。
输入:
This is a test
This is another long test
this is another long testthis is another long test
观察:
前两个输入运行良好,但对于较大的字符串(第三个输入)失败
错误:
Error in `./longest': realloc(): invalid next size: 0x000000000246e010 ***
Error in `./longest': malloc(): memory corruption (fast): 0x000000000246e030 ***
我的努力:
自 2 天以来我一直在尝试调试这个(橡皮鸭调试),但逻辑似乎很好。 GDB 指向 _getline 函数中的 realloc 调用,并在顶部显示带有 glibc.so 内存分配调用的巨大回溯。
这是我写的(部分是直接从书中摘录的):-
#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;
}
【问题讨论】:
-
认为可能需要
if(i == MAXLINE - 2){in_getline()。 -
i == MAXLINE - 2时,不会发生 realloc。如果下一个getchar(),现在是i == MAXLINE - 1,是'\n',循环结束,s[MAXLINE - 1] = '\n';。 那么s[MAXLINE]= '\0';,就是UB。 -
realloc() invalid old size 的可能重复项
-
附带说明,我花了大约 30 秒的时间认为
MAXLINE是一个常数。最好不要命名常量或宏等变量。