почему fread иногда встречает "Bad file descriptor"? - PullRequest
1 голос
/ 22 февраля 2012

Меня читают из файла, подобного следующему:

#include <stdio.h>

int main() {
    FILE *fp = fopen("sorted_hits", "r+");

    while(!feof(fp)) {
        int item_read;
        int *buffer = (int *)malloc(sizeof(int));
        item_read = fread(buffer, sizeof(int), 1, fp);
        if(item_read == 0) {
            printf("at file %ld\n", ftell(fp));
            perror("read error:");
        }
    }
}

Этот файл большой, и иногда я получаю ошибку "Bad file descriptor".«ftell» указывает, что положение файла остановилось, когда произошла ошибка.

Я не знаю, почему это «иногда», это нормально?проблема в моем коде или на жестком диске?Как справиться с этим?

Ответы [ 3 ]

5 голосов
/ 22 февраля 2012

perror печатает все, что находится в errno в виде описательной строки.errno устанавливается на код ошибки всякий раз, когда системный вызов возвращает ошибку.Но, если системный вызов НЕ ОТКАЗЫВАЕТСЯ, errno не будет изменен и будет продолжать содержать то, что содержалось ранее.Теперь, если fread возвращает 0, это означает, что либо произошла ошибка, либо вы достигли конца файла.В последнем случае errno не задан и может содержать какой-либо случайный мусор из ранее.

Так что в этом случае полученное вами сообщение «Bad file descriptor», вероятно, просто означает, что его не былоошибка вообще.Вы должны проверить ferror(fp), чтобы увидеть, произошла ли ошибка.

1 голос
/ 22 февраля 2012

Вы, похоже, смешиваете текстовый и двоичный режимы при чтении файла.

Обычно, когда вы используете fread, вы читаете из двоичного файла, т.е. fread читает количество байтов, соответствующее размеру буфера, ноВы, кажется, открываете файл в текстовом режиме (r +).ftell не работает надежно с файлами, открытыми в текстовом режиме, потому что переводы строк обрабатываются не так, как другие символы.

вместо этого открывают файл в двоичном режиме (без перевода)

FILE *fp = fopen("sorted_hits", "rb+");
0 голосов
/ 22 февраля 2012

Если это действительно то, как выглядит ваш цикл, то я думаю, что вы, вероятно, получаете более или менее ложную ошибку, потому что вашему процессу просто не хватает памяти, потому что ваш цикл так сильно его пропускает (вызов malloc каждая итерация вашего цикла, но нигде не вызывается free.

Также возможно (но гораздо менее вероятно), что вы столкнулись с небольшой проблемой из-за вашего (общего, но почти всегда неправильного) использования while (!feof(fp)).

Все в printf также дает неопределенное поведение, поскольку вы не соответствовали типу преобразования и типу (хотя во многих современных системах это не имеет значения, поскольку long и int имеют одинаковый размер).

Устранение этих проблем может или не может устранить проблему, которую вы наблюдали, но, по крайней мере, если вы все еще видите ее, вы сузите возможности того, что может быть причиной проблемы.

int main() {
    FILE *fp = fopen("sorted_hits", "r+");

    int buffer;

    while(0 != fread(&buffer, sizeof(int), 1, fp))
        ; // read file but ignore contents.

    if (ferror(fp)) {
        printf("At file: %ld\n", ftell(fp));
        perror("read error: ");
    }
}
...