我已经阅读过帖子,展示了如何使用fseek和ftell来确定文件的大小.
FILE *fp;
long file_size;
char *buffer;
fp = fopen("foo.bin", "r");
if (NULL == fp) {
/* Handle Error */
}
if (fseek(fp, 0 , SEEK_END) != 0) {
/* Handle Error */
}
file_size = ftell(fp);
buffer = (char*)malloc(file_size);
if (NULL == buffer){
/* handle error */
}
Run Code Online (Sandbox Code Playgroud)
我即将使用这种技术但后来遇到了描述潜在漏洞的链接.
该链接建议使用fstat.任何人都可以评论这个吗?
R..*_*R.. 15
该链接是CERT的许多无意义的C编码建议之一.他们的理由是基于C标准允许实现的自由,但POSIX不允许这样做,因此在您fstat作为替代方案的所有情况下都无关紧要.
POSIX要求:
该"b"对修改fopen没有任何效果,即文本和二进制模式的行为相同.这意味着他们对在文本文件上调用UB的担忧是无稽之谈.
这些文件具有由写操作和截断操作设置的字节分辨率大小.这意味着他们对文件末尾的空字节随机数的关注是无稽之谈.
遗憾的是,随着他们发布的所有废话,我很难知道哪些CERT出版物需要认真对待.这是一种耻辱,因为很多都是严肃的.
如果您的目标是找到文件的大小,绝对应该使用fstat()或其朋友.这是一个更直接和更具表现力的方法 - 你实际上要求系统告诉你文件的统计数据,而不是更环绕的fseek/ftell方法.
奖励提示:如果您只想知道文件是否可用,请使用access()而不是打开文件甚至是对其进行统计.这是一个更简单的操作,许多程序员都不知道.
我倾向于同意他们的基本结论,即您通常不应该在主流代码中直接使用fseek/代码 - 但您可能也不应该使用其中任何一个。如果您想要文件的大小,则大多数代码应该使用具有清晰、直接名称的名称,例如.ftellfstatfilesize
现在,最好在fstat可用的情况下(例如)FindFirstFile在 Windows(最明显的平台,fstat通常不可用)上实现这一点。
故事的另一面是,关于二进制文件的许多(大多数?)限制fseek实际上源于 CP/M,它没有在任何地方显式存储文件的大小。文本文件的结束由 control-Z 表示。然而,对于二进制文件,您真正知道的是使用哪些扇区来存储该文件。在最后一个扇区中,您有一些未使用的数据,这些数据通常(但并非总是)填充为零。不幸的是,可能存在重要的零和/或不重要的非零值。
如果整个 C 标准是在批准之前编写的(例如,如果它于 1988 年开始并于 1989 年完成),他们可能会完全忽略 CP/M。然而,无论好坏,他们在 1982 年左右开始研究 C 标准,当时 CP/M 的使用仍然足够广泛,以至于不容忽视。当 CP/M 离开时,许多决定已经做出,我怀疑有人愿意重新审视它们。
然而,对于今天的大多数人来说,这毫无意义——如果不进行大量工作,大多数代码都不会移植到 CP/M;这是需要处理的相对较小的问题之一。让一个现代程序在仅 48K(左右)的内存中运行代码和数据是一个更严重的问题(海量存储的最大内存为 1 MB 左右将是另一个严重的问题)。
不过,CERT 确实有一个优点:您可能不应该(像通常所做的那样)找到文件的大小,分配那么多空间,然后假设文件的内容适合该文件。尽管 fseek/ftell 将为您提供现代系统的正确大小,但当您实际读取数据时,该数据可能已经过时,因此无论如何您都可能会溢出缓冲区。
| 归档时间: |
|
| 查看次数: |
17159 次 |
| 最近记录: |