假设我想阅读双打数组。 然后我使用这段代码:
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是多少?
答案 0 :(得分:3)
在你的代码中? MAX_INT
,与平台有关。通常为2,147,483,647。但这并不能保证。
您受到真实硬件和机器状态的进一步限制。 malloc
只能抓住可用的RAM。如果不存在,那就失败了。
如果您的机器中有256K的RAM,那就不多了。它远远低于256K。如果您拥有NSA的服务器和上帝自己的内存池......但是它充满了猫视频,malloc
将会失败。< / p>
您可以进行一些实际分析,并确定在执行给定任务列表的给定系统上您可以释放多少内存。或者你可以把它保留在假定硬件的一小部分,并且希望它们不会用完。我认为重要的是要认识到你的内存分配可能会失败,并且程序需要优雅地失败。
这种不确定性是动态内存对于关键系统而言不可行的原因。
答案 1 :(得分:2)
答案在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],< em>只要 ptr
指向的存储空间足够大。
您无法保证fread
实际上会读取许多元素:
7.19.8.1.2
fread
函数读入ptr
指向的数组,最多nmemb
元素,其大小由{指定{1}} [...]如果读取了部分元素,则其值是不确定的。 (强调我的)
只要size
可以分配它,您就可以用malloc
填充它,尽管fread
可以自由地读取较少数量的元素。例如,符合fread
的实现可以合理地限制为一次性读取fread
个元素。
因此,您使用min(SIZE_MAX/size, nmemb)
是错误的。您必须继续阅读,直到您完成阅读需要阅读的内容,或发生错误,或者您已达到文件末尾。 Never test for feof
prior to reading!
fread
答案 2 :(得分:1)
使用size_t n = SIZE_MAX
尝试分配最大的代码可以处理。
各种系统都有其他限制。
许多系统需要n*sizeof *array <= SIZE_MAX
calloc()/fread()
。因此,请使用n = SIZE_MAX/sizeof *array
可分配的内存可能超过实际内存calloc()
不使用内存,只需分配它。即使fread()
可能使用所有内存,因为文件输入很小。然而,依靠它并不是强有力的代码。
最后,一旦代码尝试使用其分配,就会发生内存不足的错误。
关于&#34;安全使用&#34;,代码应在NULL
之后立即检查calloc()
。
相反,建议阅读数据块,然后根据需要重新分配到一个大数组中。