为什么fread有时会遇到“错误的文件描述符”?

问题描述 投票:2回答:3

我从这样的文件中读取:

#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:");
        }
    }
}

此文件很大,有时会出现“错误文件描述符”错误。 “ ftell”表示发生错误时文件位置停止。

我不知道为什么有时是这样,这很正常吗?问题出在我的代码还是在硬盘上?如何处理?

c file stream fread
3个回答
6
投票

perrorerrno中的所有内容打印为描述性字符串。每当系统调用返回错误时,errno就会设置为错误代码。但是,如果系统调用不会失败,则errno不会被修改,并且将继续包含以前包含的所有内容。现在,如果fread返回0,则意味着出现错误或者您到达文件末尾。在后一种情况下,未设置errno,并且可能包含之前的任何随机垃圾。

因此,在这种情况下,您可能收到的“错误文件描述符”消息仅表示根本没有错误。您应该检查ferror(fp)以查看是否发生了错误。


2
投票

读取文件时,您似乎在混合文本和二进制模式。

[通常,当您使用fread时,您从二进制文件读取,即fread读取了一些与缓冲区大小匹配的字节,但是您似乎正在以文本模式(r +)打开文件。 ftell在以文本模式打开的文件上无法可靠工作,因为换行符与其他字符的区别。

改为以二进制模式打开文件(未翻译):

FILE *fp = fopen("sorted_hits", "rb+");

1
投票

如果这确实是您的循环的样子,我猜您可能会收到或多或少的虚假错误,因为您的进程正快用完内存,因为您的循环泄漏得非常严重(每次调用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: ");
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.