gpt4 book ai didi

c - 使用 fseek(file, 0, SEEK_END) 和文件了解二进制流的未定义行为

转载 作者:太空狗 更新时间:2023-10-29 16:41:38 25 4
gpt4 key购买 nike

C 规范有一个有趣的脚注 (#268 C11dr §7.21.3 9)

"Setting the file position indicator to end-of-file, as with fseek(file, 0, SEEK_END), has undefined behavior for a binary stream (because of possible trailing null characters) or for any stream with state-dependent encoding that does not assuredly end in the initial shift state."

这是否适用于读取文件的二进制流?(来自物理设备)

IMO,磁盘上的二进制文件只是字节的海洋。在我看来,二进制文件不能有状态相关的编码,因为它是一个二进制文件。我对“二进制宽向流”的概念很模糊,如果它甚至可以应用于磁盘 I/O。

我看到在像 com 端口或 stdin 这样的串行流上调用 fseek(file, 0, SEEK_END) 可能不会到达真正的终点,因为 < em>end 尚未确定。因此将问题缩小到物理文件。


[edit] 答案:对老年人的担忧(可能到 1980 年代后期)。目前在 2014 年,Windows、POSIT 特定和非奇异的其他:不是问题。

@Shafik Yaghmour 在 Using fseek and ftell to determine the size of a file has a vulnerability? 中提供了很好的引用.有@Jerry Coffin 讨论CP/M因为二进制文件并不总是具有精确的长度。 (每个 wiki 128 字节记录)。

感谢@Keith Thompson 的回答。

这一起解释了规范的“(因为可能存在尾随空字符)”注释。

最佳答案

二进制文件将是 8 位字节序列,具有精确指定的大小,适用于您可能使用的任何系统。但并非所有系统都以这种方式存储文件,并且 C 标准经过精心设计以允许可移植到具有异常特征的系统。

例如,符合标准的 C 实现可能会在操作系统上运行,该操作系统将文件存储为 512 字节 block 的序列,没有指示最终 block 中有多少字节是重要的。在这样的系统上,当创建二进制文件时,操作系统可能会用零字节填充最后一个 block 的剩余部分。当您从这样的文件中读取时,填充字节可能会出现在输入中(即使它们从未明确写入文件),或者它们可能会被忽略(即使创建文件的程序可能已经明确写入它们) .

如果您正在从不可搜索的流(例如键盘输入)中读取数据,那么 fseek(file, 0, SEEK_END) 不仅会给您一个糟糕的结果,它还会指示通过返回非零结果失败。 (在符合 POSIX 的系统上,它返回 -1 并设置 errno;ISO C 不需要这样做。)

在大多数系统上,二进制文件上的 fseek(file, 0, SEEK_END) 将寻找到文件的实际末尾(该位置由写入文件的字节数决定) ), 或者返回一个明确的失败指示。如果您无论如何都在使用特定于 POSIX 的功能,那么您可以安全地假设这种行为;您可能会对 Windows 和许多其他系统做出相同的假设。如果您希望您的代码 100% 可移植到异国情调的系统,您不应该假设二进制文件不会用额外的零字节填充。

关于c - 使用 fseek(file, 0, SEEK_END) 和文件了解二进制流的未定义行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21050603/

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