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

发布于 2025-01-07 12:34:17 字数 511 浏览 0 评论 0原文

我从这样的文件中读取:

#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”表示发生错误时文件位置停止。

我不知道为什么是“有时”,这正常吗?问题出在我的代码还是硬盘上?这要怎么处理呢?

I am read from a file like this:

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

This file is big and I got the "Bad file descriptor" error sometimes. "ftell" indicates that the file position stopped when error occurred.

I don't know why it is "sometimes", is that normal? does the problem lie in my code or in my hard disk? How to handle this?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

牵你的手,一向走下去 2025-01-14 12:34:17

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

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

perror prints whatever is in errno as a descriptive string. errno gets set to an error code whenever a system call has an error return. But, if a system call DOESN'T fail, errno doesn't get modified and will continue to contain whatever it contained before. Now if fread returns 0, that means that either there was an error OR you reached the end of the file. In the latter case, errno is not set and might contain any random garbage from before.

So in this case, the "Bad file descriptor" message you're getting probably just means there hasn't been an error at all. You should be checking ferror(fp) to see if an error has occurred.

葬花如无物 2025-01-14 12:34:17

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

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

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

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

You seem to be mixing text and binary modes when reading the file.

Normally when you use fread you read from a binary file i.e. fread reads a number of bytes matching the buffer size but you seem to be opening the file in text mode (r+). ftell doesn't work reliably on files opened in text mode because newlines are treated differently than other characters.

Open the file in binary mode (untranslated) instead:

FILE *fp = fopen("sorted_hits", "rb+");
感受沵的脚步 2025-01-14 12:34:17

如果这确实是您的循环的样子,我的猜测是您可能会遇到或多或少的虚假错误,因为您的进程刚刚耗尽内存,因为您的循环严重泄漏内存(调用 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: ");
    }
}

If that's really what your loop looks like, my guess would be that you're probably getting a more or less spurious error because your process is just running out of memory because your loop is leaking it so badly (calling malloc every iteration of your loop, but no matching call to free anywhere).

It's also possible (but a lot less likely) that you're running into a little problem from your (common but nearly always incorrect) use of while (!feof(fp)).

Your all to printf also gives undefined behavior because you've mismatched the conversion and the type (though on many current systems it's irrelevant because long and int are the same size).

Fixing those may or may not remove the problem you've observed, but at least if you still see it, you'll have narrowed down the possibilities of what may be causing the problem.

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: ");
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文