2

我在传递 to 的值时会遇到问题off_tmalloc()期望在哪里size_t)?

我正在读取一个文件并将其内容存储到内存中。文件大小由st_size成员从struct stat传递给stat()函数后获取,然后传递到malloc()我将调用的地方,以fread()传递返回的内存malloc()asbuf和文件大小 as nmemb

但问题是:如果文件大小真的是一个大数字,32 位/64 位机器上size_t的函数行为是什么:整数溢出和损坏的 buf(不是请求的字节数是malloc()真的回来了)还是NULL

我知道它可能真的永远不会发生,所以可能有人使用这个应用程序进入例如超级计算机并向我的解析器请求一个最大的文件......但我真的很想了解事情的最大可能,甚至永远不会发生的行为.

4

2 回答 2

1

的,你会有问题。首先,通过尝试首先读取文件大小,您实际上是在禁止您的用户使用例如管道。您绝对需要随机访问文件中的数据吗?如果没有,请尝试以面向流的方式解析您的文件。如果您绝对需要它在内存中,那么您可以使用stat首先验证文件大小是否大于可以容纳的大小off_t(请注意,如果文件大小不适合结构,stat则会失败)或大于可以容纳的大小(比较to or ),如果是这样的话,请尽早保释(即使您以某种方式将其读入 RAM,您的进程也没有足够的指针中的位来寻址它),否则尝试errno==EOVERFLOWstatsize_tst_sizeSIZE_MAX((size_t)-1)malloc(并检查NULL返回值)或者更好的是mmap(如果可用)您的文件。


后脚本

@R 不喜欢我提到stat64,因为它是非标准的(即非 POSIX。)从技术上讲这是非常正确的,但实际上stat64在 Linux、Solaris、OSX、HP-UX、AIX、QNX 上很容易获得(并记录在案) ,甚至在 Windows 的 MSVCRT 中。它在 OpenBSD 上不可用,因为在 OpenBSD 上常规stat已经支持大文件

检索 >2GB 文件大小的传统(并且更标准_LARGEFILE_SOURCE)方法是使用,_LARGEFILE64_SOURCE和进行构建_FILE_OFFSET_BITS=64,这可能会使stat行为类似于stat64(您仍然必须确定是否sizeof(off_t) >= 64/8确定是否支持 8TB。)

事情的真相是,就您而言,以上所有内容都是学术性的。您不需要知道初始检查的确切文件大小,只有当它超过 和 的较小者可以容纳的大小off_tsize_t。我已经相应地更新了原始答案,顶部。

于 2012-11-18T17:05:52.260 回答
1

您希望文件大小有多大?对于中等到大的文件(比如几个 MiB,但小于 2 GiB),你不会有问题。如果您的文件大于 2 GiB,并且您使用的是 32 位系统,那么您将遇到各种问题。如果您的文件大于 2 GiB,但您使用的是 64 位 (Unix) 机器,则问题主要出在可用的物理内存上(以避免抖动)。考虑使用mmap()不管。

但问题是:如果文件大小真的是一个 size_t 无法容纳的大数字,那么 malloc() 函数在 32 位/64 位机器上的行为是什么?

如果 in 的值off_t大于可以容纳的范围size_t(在 32 位系统上完全合理;在 Windows 64 以外的 64 位系统上不合理),那么malloc()将“工作”但会分配所需的空间值的低位off_t。这不是你想要的。作为一个具体但似是而非的例子:如果off_t是 64 位数量但是size_t32 位数量,则 的低位off_t将用作 的大小malloc(),而忽略高位。如果高位全为零,那不是问题。如果设置了任何高位,您将滥用未分配的内存。

请注意,malloc()无法检测问题。它是size_t由编译器给出的,因为其中的声明<stdlib.h>说这是正确的类型。这完全取决于编译器是否警告您截断。它没有义务警告您可能出现的问题。

在大文件大小时,您必须了解所使用类型的限制,并且您必须非常小心以确保获得您期望的结果(而不仅仅是您要求的结果,这不是必然是同一件事)。

于 2012-11-18T17:03:04.663 回答