gpt4 book ai didi

c - 在文件结束前只有部分记录可用时 fread 的行为

转载 作者:行者123 更新时间:2023-12-03 21:06:04 26 4
gpt4 key购买 nike

我研究什么可以被看作是一个 C 解释器,它检测它解释的程序中的所有未定义的行为。在使用此解释器查找遗留开源 C 应用程序中的错误时,我对以下行为感到困惑:
遗留应用程序需要一个 10 字节的 header ,它需要完整的 header 才能做进一步的工作。它正确地调用了 fread(buffer, 10, 1, f); .错误地,它没有分配 fread 的结果调用,并立即开始解析缓冲区。
当这个fread应用于可用字节少于 10 字节的文件,发生的情况是 buffer部分归档了可用数据。解释器,正如它设计的那样,检测到缓冲区的未初始化部分稍后被使用并警告了这一点,我能够将问题追溯到 fread 的结果。被丢弃。fread让我困惑了一分钟我的同事写的部分填充了缓冲区,即使它会返回 0最终,我想知道这是否可以改进。很明显,一些实现确实读入缓冲区,最后返回读取记录的数量为 return n_bytes / __size; ,让除法四舍五入,在本例中为 0 .但我想知道其他实现是否可能只写入 buffer如果整个记录可用,否则将其完全未初始化。
实际上,在我手头的两个 Unices 上,fread行为方式与我同事编写的模型实现相同:

~ $ cat t.c
#include <stdio.h>
#include <stdlib.h>

char buffer[11] = "0000000000";

int main(void) {

FILE *f = fopen("aaaa", "r");
if (!f) exit(1);
int r = fread(buffer, 10, 1, f);
printf("%s\n", buffer);
}
~ $ gcc t.c && ./a.out
aaaa000000
~ $ uname -a
Darwin tis-laptop-6.local 16.7.0 Darwin Kernel Version 16.7.0: Sun Jun 2 20:26:31 PDT 2019; root:xnu-3789.73.50~1/RELEASE_X86_64 x86_64
测试程序在带有 Glibc 的 Linux 上也产生相同的结果(文件 aaaa 包含 aaaa)。
分析每种情况下发生的情况将花费不合理的成本“ fread部分填充最后一条记录”和“ fread在解释器的缓冲区中保留最后部分记录不变”,但我们可以使缓冲区中应该接收到只有部分数据的记录的部分未初始化,以防止解释的 C 程序依赖它。但是当 fread 时,这又会令人费解。传递一个已经初始化的缓冲区。
所以我发现自己想知道解释器的行为是否是 fread目前有,而且 macOS 和 Linux/Glibc 也有,是有保证的(在这种情况下一切都很好)。
我找到了 this related question . This comment似乎表明 fread我在所有三个实现中观察到的行为是唯一可能的,但我想明确确认(或不) fread可以假设读取所有可用的字符,直到 size * nmemb即使可用字符数不是 size 的倍数.

最佳答案

两者 C99 (第 7.19.8.2 节)和 C11 (第 7.21.8.2 节)定义 fread()具有以下描述:

The fread function reads, into the array pointed to by ptr, up to nmemb elements whose size is specified by size, from the stream pointed to by stream. For each object, size calls are made to the fgetc function and the results stored, in the order read, in an array of unsigned char exactly overlaying the object. The file position indicator for the stream (if defined) is advanced by the number of characters successfully read. If an error occurs, the resulting value of the file position indicator for the stream is indeterminate. If a partial element is read, its value is indeterminate.


最后一点应该可以消除您的疑虑:

If a partial element is read, its value is indeterminate.


因此,即使您看到的所有实现看起来都表现得“很好”,但您不能依赖它,因为标准没有定义依赖于实现的行为。希望读取部分元素(如果文件包含一个)的程序应该使用 size1并检查返回值。事实上,如果一个程序不这样做而是用 size > 1 读取和 nmemb = 1 ,在最后一个部分元素的情况下,它甚至无法区分进入缓冲区的初始化数据和未初始化数据。

关于c - 在文件结束前只有部分记录可用时 fread 的行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66627957/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com