读取二进制文件时的最大大小是多少?
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
来尝试分配最大的代码可以处理。
各种系统有其他限制。
许多系统需要 n*sizeof *array <= SIZE_MAX
才能 calloc()/fread()
。所以使用 n = SIZE_MAX/sizeof *array
可分配内存,可能比实际内存多,因为 calloc()
不使用内存,只是分配内存。即使 fread()
也可能不会 使用 由于文件输入很小而给定的所有内存。然而,指望那不是健壮的代码。
最后,一旦代码尝试使用它的分配,就会发生内存不足的错误。
关于 "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] 没有提供任何限制,size
和 nmemb
的值可以达到其类型提供的最大值 - 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);
}
}
假设我想读取双精度数组。 然后我使用这个代码:
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
来尝试分配最大的代码可以处理。
各种系统有其他限制。
许多系统需要
n*sizeof *array <= SIZE_MAX
才能calloc()/fread()
。所以使用n = SIZE_MAX/sizeof *array
可分配内存,可能比实际内存多,因为
calloc()
不使用内存,只是分配内存。即使fread()
也可能不会 使用 由于文件输入很小而给定的所有内存。然而,指望那不是健壮的代码。最后,一旦代码尝试使用它的分配,就会发生内存不足的错误。
关于 "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] 没有提供任何限制,size
和 nmemb
的值可以达到其类型提供的最大值 - SIZE_MAX
[7.18.3.2] , 只要 ptr
指向的存储有足够的大小。
您不能保证 fread
实际上会读取那么多元素:
7.19.8.1.2 The
fread
function reads, into the array pointed to byptr
, up tonmemb
elements whose size is specified bysize
[...] 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);
}
}