读取二进制文件时的最大大小是多少?

What is maximum size when read binary files?

假设我想读取双精度数组。 然后我使用这个代码:

FILE *fp;
int n=100;
fp=fopen("file.bin","rb");
double *array=(double*)calloc(n,sizeof(double));
fread(array,sizeof(double),n,fp);
fclose(fp);

我可以安全地用于 fread() 函数的最大 n 是多少?

在你的代码中? MAX_INT,这取决于平台。通常为 2,147,483,647。但这并不能保证。

您进一步受到现实世界硬件和机器状态的限制。 malloc只能去抢可用的RAM。如果它不存在,它就会失败。 如果你的机器有 256K 的 RAM,那也不算多。它远小于256K。如果你有 NSA 的服务器和上帝自己的内存池...但里面塞满了猫视频,malloc 将在任何值下失败。

您可以进行一些实际分析,并确定在执行给定任务列表的给定系统上有多少可用内存。或者您可以将它保留在假定硬件的一小部分,只是希望它们不会 运行 出来。我想说重要的是要认识到您的内存分配可能会失败,并且程序需要优雅地失败。

这种不确定性是动态内存对于关键系统来说是不可取的原因。

使用size_t n = SIZE_MAX尝试分配最大的代码可以处理。

各种系统有其他限制。

  1. 许多系统需要 n*sizeof *array <= SIZE_MAX 才能 calloc()/fread()。所以使用 n = SIZE_MAX/sizeof *array

  2. 可分配内存,可能比实际内存多,因为 calloc() 不使用内存,只是分配内存。即使 fread() 也可能不会 使用 由于文件输入很小而给定的所有内存。然而,指望那不是健壮的代码。

  3. 最后,一旦代码尝试使用它的分配,就会发生内存不足的错误。

关于 "safely use",代码应在 calloc().

之后立即检查 NULL

相反,建议读取数据块并在以后需要时重新分配到一个大数组中。

C 标准 7.19.8 中提供了答案。我将使用 N1256 草稿。

size_t fread(void * restrict ptr,
          size_t size, size_t nmemb,
          FILE * restrict stream);

由于 [7.19.8.1] 没有提供任何限制,sizenmemb 的值可以达到其类型提供的最大值 - SIZE_MAX [7.18.3.2] , 只要 ptr指向的存储有足够的大小。

您不能保证 fread 实际上会读取那么多元素:

7.19.8.1.2 The fread function reads, into the array pointed to by ptr, up to nmemb elements whose size is specified by size [...] If a partial element is read, its value is indeterminate. (emphasis mine)

只要malloc能分配到,就可以用fread填满,虽然fread可以自由读取较少的元素。例如,一致的 fread 实现可以合理地限制为一次性读取 min(SIZE_MAX/size, nmemb) 个元素。

因此,您对 fread 的使用是错误的。您必须继续阅读,直到读完需要阅读的内容,或者发生错误,或者到达文件末尾。 Never test for feof prior to reading!.

void processData(double * data, size_t count);

void readData(void) {
  FILE *file = fopen("file.bin","rb");
  size_t n = 100;

  if (file) {
    double * array = calloc(n, sizeof(double));
    double * head = array;
    if (!array) break;
    while (n) {
      size_t n_read = fread(head, sizeof(double), n, file);
      head += n_read;
      n -= n_read;
      if (feof(file) || ferror(file)) break;
    }
    processData(array, head-array);
    fclose(file);
  }
}