Программа не работает для больших файлов в C - PullRequest
0 голосов
/ 07 ноября 2011

Я использую следующую программу на C для фильтрации файла журнала с 200 000 строк.Но программа перестает отвечать после примерно 12000 строк.Любые объяснения, почему это происходит, и какое-либо решение для этого?Код скомпилирован в GCC (windows).

PS: код выполняется правильно и выдает желаемый результат для небольших файлов.

#include<stdio.h>
#include<string.h>

int check(char *url)
{
    //some code to filter the data and return either 0 or 1 depending upon input
}

int main()
{
    FILE *fpi, *fpo;
    fpi=fopen("access.log","r");
    fpo=fopen("edited\\filter.txt","w");
    char date[11],time[9],ip[16],url[500],temp[3];
    while(!feof(fpi))
    {
        printf(".");
        fscanf(fpi," %s %s %s %s %s %s",date,time,temp,ip,temp,url);
        if(check(url)) 
            fprintf(fpo,"%s %s %s %s %s %s\n",date,time,temp,ip,temp,url);
    }
    fclose(fpi);
    fclose(fpo);
    printf("\n\n\nDONE! :)");
    return 0;
}

1 Ответ

6 голосов
/ 07 ноября 2011

Возможно, что одна из строк во входном файле содержит поле, которое больше, чем строковая переменная, которую вы передаете fscanf(). Это может привести к переполнению буфера, что позже приведет к бесконечному циклу. Просто предположение. Я предлагаю разделить %s в строке формата fscanf() с максимальной длиной выходной строковой переменной.

Например, это обеспечит отсутствие переполнения буфера и завершение строк:

 fscanf(fpi," %10s %8s %2s %15s %49s %2s", date, time, temp, ip, temp, url);
 date[10] = '\0';
 time[8] = '\0'; 
 ip[15] = '\0'; 
 temp[2] = '\0'; 
 url[499] = '\0'; 

Кроме того, вы читаете темп дважды. Последнее чтение переопределит первое. Это то, что вы намеревались?

Другое улучшение, предполагающее, что входной файл заканчивается строкой, а каждый журнал находится в отдельной строке, - это использование fgets() для чтения строки и только затем использование sscanf() в промежуточном буфере. Таким образом, вы гарантируете, что ошибки форматирования не выходят за пределы одной строки. Кроме того, sscanf возвращает количество прочитанных элементов, в вашем случае - 6. Было бы безопаснее проверить возвращаемое значение.

...