C中size_t类型的malloc参数的限制是什么?Docs说它有UINT_MAX的上限但我不能超越INT_MAX

Ros*_*han 3 c malloc size-t limit

我想分配一个2.9GB的char数组

  database = (char*) malloc((2900 * 1000000 * sizeof(char)));
Run Code Online (Sandbox Code Playgroud)

这给出了整数溢出警告和malloc返回NULL.的 malloc参数的类型的size_t根据文档其是类型的 unsigned int.

所以最大应该UINT_MAX是至少2.9GB.但是,如果我尝试分配超过MAX_INTmalloc失败.这是否意味着 size_t我的系统是int类型?我该如何检查?我看了看

/usr/include/stdlib.h 
Run Code Online (Sandbox Code Playgroud)

./lib/gcc/x86_64-redhat-linux/4.1.1/include/stddef.h 
Run Code Online (Sandbox Code Playgroud)

但找不到定义size_t.非常感谢

R..*_*R.. 10

参数是类型的size_t,malloc并且需要接受任何可能的类型值size_t.请注意,"接受"并不意味着需要分配那么多; 所有这意味着,malloc由于溢出问题,不允许误解一个非常大的数字作为一个小/负数,从而返回一个太小的缓冲区,并创建一个程序无法防范的关键不可检测的漏洞.有许多可能的原因malloc可能无法分配非常大的对象:

  • 系统无法提供大量内存
  • 由于碎片,没有大的可用连续范围的虚拟地址
  • 任意限制

在这种情况下,我怀疑你可能会看到第三个任意限制,但我不认为它们是如此随意.有一个很好的理由不允许分配(以及任何对象的存在)大于SIZE_MAX/2:取这些大对象中的指针之间的差异将导致(极其危险的)整数溢出和未定义的行为,当结果不适合(签名) )类型ptrdiff_t.因此,在强大的32位系统上,当虚拟地址空间大小为4GB时,任何单个对象的最大大小将为2GB.

  • 关于`ptrdiff_t`签字的好点. (3认同)

Jam*_*lis 9

这里有两个问题.

首先,溢出警告:both 29001000000都是类型int,因此乘以它们的结果也是类型int.结果不能用32位有符号整数表示,因此它会溢出.您需要转换一个(或两个)参数size_t以使用无符号算术.

(或者,您可以将其移动为sizeof(char)前两个术语之一,因为它的类型是size_t,但您也可以删除sizeof(char)它,因为它总是1.)

其次,malloc可以分配的最大大小取决于您运行的平台和程序的当前状态.如果没有足够的连续地址空间来满足请求,显然malloc会失败.

此外,您运行的平台可能有一个上限,它可以动态分配一个对象的大小.您需要查阅平台的文档以了解该上限是什么.

size_t肯定不是int,因为int总是签名并且size_t总是没有签名.