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

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

database = (char*) malloc((2900 * 1000000 * sizeof(char))); 

这给出了整数溢出警告, malloc返回NULLmalloc参数的类型为size_t ,根据文档的类型为unsigned int

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

 /usr/include/stdlib.h 

 ./lib/gcc/x86_64-redhat-linux/4.1.1/include/stddef.h 

但是找不到size_t的定义。 非常感谢

这里有两个问题。

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

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

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

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

size_t肯定不是int ,因为int总是有符号的,而size_t总是无符号的。

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

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

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

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