Я реализовал HTTP-клиент, который может получать контент, указав имя и порт хоста и отображая его по строке из сокета. Ниже мое чтение одна строка функции:Чтение сокета по строке, но проблема с памятью возникает
char* getLine(int fd)//fd is the socket number created before
{
char c, pre;
char* line = 0;
int size = 0;
while(read(fd, &c, 1)!=0)
{
line = realloc(line, ++size);//read a new char so re-allocation
line[size - 1] = c;
if(pre == '\r' && c == '\n')//this is a new line
{
break;
}
pre = c;
}
if(line)
{
line = realloc(line, ++size);
line[size - 1] = 0;//add a \0 at the end of line
}
return line;
}
Ниже, как я использую эту функцию в основной функции (при условии, sockfd был создан и запрос был отправлен на сервер)
char* line;
while((line = getLine(sockfd)) != NULL)
{
printf("%s", line);
if(!strcmp(line, "\r\n"))//blank line
printf("#####Now reading body.\n");
free(line);
}
Проблема заключается в том , когда я пытаюсь получить контент с нескольких коротких страниц, таких как google.com или yahoo.com, он отлично работает. Однако, если я хочу попробовать длинную страницу, например, www.stanford.edu, она показывает realloc(): invalid next size: 0x0000000000c794b0 ***
.
Похоже, что мой указатель имеет некоторые неопределенные поведения в функции getLine
, но я действительно не знаю, где проблема. Может ли кто-нибудь дать мне какой-то намек? Благодаря!
** Проблема решена, поэтому исходный код удален.
Использование realloc и увеличение байта размера байтом происходит медленно, что приводит к квадратичному поведению. Обычный трюк состоит в том, чтобы удвоить размер выделения каждый раз, когда вам нужно больше места (кроме «добавить нулевой»). Вы также можете уменьшить распределение негабаритных величин в соответствии с точными требованиями. Тем не менее, это напрямую не связано с вашей проблемой/ошибкой. –
Компилятор должен предупредить вас о том, что 'может использовать переменную 'pre', не инициализированную в этой функции'; инициализируйте его равным 0. Вы должны проверить, что 'realloc()' не возвращает ошибку - нулевой указатель. Кроме того, если это произойдет, вы пропустите память, потому что вы потеряли предыдущий ненулевой указатель. Всегда используйте некоторый вариант на 'void * new_space = realloc (old_space, new_size); if (new_space! = 0) old_space = new_space; '. –
'while (read (fd, & c, 1)! = 0)' read может возвращать -1 (который действует как 'true') ... просто говоря ... – wildplasser