我想用分配一个2.9GB的char数组
database = (char*) malloc((2900 * 1000000 * sizeof(char)));
这会发出整数溢出警告,并且malloc
返回NULL
。这个malloc
参数的类型为size_t
,根据文件,其类型为unsigned int
。
因此,最大值应该是UINT_MAX
,至少为2.9GB。但是,如果我试图分配超过MAX_INT
的malloc
失败。这意味着我的系统上的size_t
的类型是int?我该如何检查?我浏览了
/usr/include/stdlib.h
和
./lib/gcc/x86_64-redhat-linux/4.1.1/include/stddef.h
但是找不到CCD_ 10的定义。非常感谢
参数的类型为size_t
,malloc
需要接受任何可能的size_t
类型的值。请注意,"接受"并不意味着需要分配那么多;这意味着malloc
不允许由于溢出问题而将你给它的一个很大的数字误解为一个小/负数,从而返回一个太小的缓冲区,并创建一个你的程序无法防御的无法检测的关键漏洞。malloc
可能无法分配非常大的对象,原因有很多:
- 系统没有那么多内存
- 由于碎片化,没有那么大的连续虚拟地址范围可用
- 任意极限
在这种情况下,我怀疑你可能看到了第三个任意的限制,尽管我不认为它们是如此武断。有一个很好的理由不允许大于SIZE_MAX/2
的分配(以及任何对象的存在):当结果不适合(带符号)类型ptrdiff_t
时,在这样大的对象中获取指针之间的差异将导致(极其危险的)整数溢出和未定义行为。因此,在健壮的32位系统上,虽然虚拟地址空间大小为4GB,但任何单个对象的最大大小都将为2GB。
这里有两个问题。
首先,溢出警告:2900
和1000000
都是int
类型,所以相乘的结果也是int
类型。结果不能用32位有符号整数表示,因此会溢出。您需要将一个(或两个)参数强制转换为size_t
才能使用无符号算术。
(或者,您可以将sizeof(char)
移动为前两个项之一,因为它的类型是size_t
,但也可以删除sizeof(char)
,因为它总是1
。)
其次,malloc
可以分配的最大大小取决于运行的平台和程序的当前状态。如果没有足够的连续地址空间来满足请求,那么显然malloc
将失败。
此外,您运行的平台可能对其可以动态分配的对象大小有上限。您需要查阅您的平台文档,以了解上限是多少。
size_t
当然不是int
,因为int
总是有符号的,而size_t
总是无符号的。
malloc可以分配的最大大小取决于运行的平台和程序的当前状态。如果没有足够的连续地址空间来满足请求,malloc显然会失败。