【问题标题】:why fread sometimes encounters "Bad file descriptor"?为什么 fread 有时会遇到“错误的文件描述符”?
【发布时间】:2012-03-12 12:06:09
【问题描述】:

我是从这样的文件中读取的:

#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


    【解决方案1】:

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

    通常,当您使用 fread 时,您会从二进制文件中读取数据,即 fread 会读取与缓冲区大小匹配的字节数,但您似乎是以文本模式 (r+) 打开文件。 ftell 不能可靠地处理以文本模式打开的文件,因为换行符的处理方式与其他字符不同。

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

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

    【讨论】:

    • 这实际上是我的问题!我的文件是用“r”模式打开的,nealry all go file,但是当文件中有一些特殊字符(我无法找出确切的字符)时,读取命令失败并出现错误“错误文件描述符”。所以感谢您的提示,它解决了我的问题!
    • @MeisterSchnitzel 很高兴我能帮上忙 :)
    【解决方案2】:

    如果这真的是你的循环的样子,我猜你可能会或多或少地得到一个虚假的错误,因为你的进程只是内存不足,因为你的循环泄漏得太厉害了(调用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: ");
        }
    }
    

    【讨论】:

      【解决方案3】:

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

      所以在这种情况下,您收到的“错误文件描述符”消息可能只是意味着根本没有错误。您应该检查ferror(fp) 以查看是否发生错误。

      【讨论】:

      • 除此之外,在调用 perror("") 之前的 printf("at file %ld\n", ftell(fp)); 行可以设置 errno ,因此它可能不是打印的 fread 的 errno。
      猜你喜欢
      • 2016-08-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-09-08
      • 1970-01-01
      • 1970-01-01
      • 2019-06-11
      相关资源
      最近更新 更多