2015-02-05 13 views
0

Я реализовал 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, но я действительно не знаю, где проблема. Может ли кто-нибудь дать мне какой-то намек? Благодаря!

** Проблема решена, поэтому исходный код удален.

+1

Использование realloc и увеличение байта размера байтом происходит медленно, что приводит к квадратичному поведению. Обычный трюк состоит в том, чтобы удвоить размер выделения каждый раз, когда вам нужно больше места (кроме «добавить нулевой»). Вы также можете уменьшить распределение негабаритных величин в соответствии с точными требованиями. Тем не менее, это напрямую не связано с вашей проблемой/ошибкой. –

+1

Компилятор должен предупредить вас о том, что 'может использовать переменную 'pre', не инициализированную в этой функции'; инициализируйте его равным 0. Вы должны проверить, что 'realloc()' не возвращает ошибку - нулевой указатель. Кроме того, если это произойдет, вы пропустите память, потому что вы потеряли предыдущий ненулевой указатель. Всегда используйте некоторый вариант на 'void * new_space = realloc (old_space, new_size); if (new_space! = 0) old_space = new_space; '. –

+0

'while (read (fd, & c, 1)! = 0)' read может возвращать -1 (который действует как 'true') ... просто говоря ... – wildplasser

ответ

4

Буфер, который вы выделяете в createQuery(), слишком мал.

Вычисленная длина не учитывает HTTP_VERSION и не учитывает завершающий \ 0 байт. Результатом является повреждение памяти и неопределенное поведение.

+0

Спасибо, ты спасатель жизни! – TonyLic