fgets читает больше данных из закрытого файлового дескриптора - PullRequest
2 голосов
/ 07 сентября 2011

У меня проблемы с fgets () в linux.fgets возвращает мне данные из закрытого файлового дескриптора.Я ожидаю, что он вернет EOF, если файл был закрыт.Я могу предложить упрощенную версию своей проблемы.

int main()
{
        int i=0, j;
        FILE *FD;
        char p[128];
        FD = fopen("junk", "r");
        while(fgets(p, sizeof(p), FD))
        {  
                close(fileno(FD));
                printf("lineno=%d\n", i++);
        }  
        return 0;
}

Я ожидаю, что она напечатает только одну строку.Есть ли способ обойти эту проблему?

Обновление: как кто-то ответил ниже, fgets буферизует файл и возвращает мне данные даже после закрытия FD.Он буферизует 4 КБ данных.Если размер файла больше 4 КБ, он получает EOF после чтения 4 КБ, и печать останавливается.Иначе, если размер файла меньше, спасибо 4k, он печатается до конца файла.

Ответы [ 3 ]

5 голосов
/ 07 сентября 2011

Вызов fgets () для закрытого файла имеет неопределенное поведение.Другими словами, не гарантируется возврат EOF.

1 голос
/ 07 сентября 2011

Как уже говорили другие, close(fileno(FD)); - плохая идея.Если вы сделаете это, тот же файловый дескриптор может быть повторно использован для другого файла, и fgets внезапно прочитает этот fd вместо этого.Это особенно вероятно для многопоточных приложений.

Кроме того, fgets буферизуется.Вероятно, он прочитал большой кусок данных или около того из файла при первом вызове, а последующие вызовы просто возвращают больше данных из буфера.

Вместо этого сделайте что-то вроде этого:

int main(void)
{
        int i=0, j;
        FILE *FD;
        char p[128];
        FD = fopen("junk", "r");
        while(FD && fgets(p, sizeof(p), FD))
        {  
                fclose(FD);
                FD = NULL;
                printf("lineno=%d\n", i++);
        }  
        return 0;
}
0 голосов
/ 07 сентября 2011

Использование дескриптора файла после закрытия может привести к непредсказуемому / неопределенному поведению.Вам, вероятно, следует избегать этого.

В опубликованном примере, вероятно, происходит то, что поток открывается и читается.Чтение данных, возможно, поместит больше данных в основной поток.Таким образом, даже если базовый дескриптор файла закрыт, дескриптор потока все равно будет содержать больше данных для чтения.Опять же, это, вероятно, непредсказуемо.

...