【发布时间】:2014-05-08 00:41:24
【问题描述】:
情况如下:
- 32 位整数溢出
- malloc,期望一个 64 位整数使用这个整数作为输入
现在在 64 位机器上,哪个语句是正确的(如果有的话):
假设有符号二进制整数 11111111001101100000101011001000 由于溢出而只是负数。这是一个实际存在的问题,因为您可能希望分配比 32 位整数所能描述的更多的字节。但随后它会以 64 位整数的形式读入。
-
Malloc将其读取为 64 位整数,发现11111111001101100000101011001000################################与 # 是通配符位,表示存储在原始整数之后的任何数据。换句话说,它读取的结果接近其最大值 2^64 并尝试分配一些 quintillion 字节。它失败了。 -
Malloc将其读取为 64 位整数,转换为0000000000000000000000000000000011111111001101100000101011001000,可能是因为它是如何加载到寄存器中而留下很多位为零的。它不会失败,而是分配负内存,就像读取正的无符号值一样。 -
Malloc将其读取为 64 位整数,转换为################################11111111001101100000101011001000,可能是因为它是如何加载到带有 # 通配符的寄存器中的,该通配符表示寄存器中先前存在的任何数据。根据最后一个值,它会非常不可预测地失败。 - 整数根本不会溢出,因为即使它是 32 位,它仍然在 64 位寄存器中,因此 malloc 可以正常工作。
我实际上对此进行了测试,导致 malloc 失败(这意味着 1 或 3 是正确的)。我认为 1 是最合乎逻辑的答案。我也知道解决方法(使用 size_t 作为输入而不是 int)。
我真的很想知道实际发生了什么。出于某种原因,对于这种意外的“强制转换”,我没有找到任何关于如何在 64 位机器上实际处理 32 位整数的说明。我什至不确定它是否在寄存器中真的很重要。
【问题讨论】:
-
这取决于架构。有些架构本身实际上并没有 32 位数字,它们将所有操作视为 64 位。不管有符号溢出是未定义的行为,无符号溢出都有很好的文档记录,并涵盖在二进制补码的工作原理中。
-
@nikolaMM94 但是,溢出有符号整数是未定义的行为 - 根据情况可能会发生很多不同的事情。
-
这种情况的规则在标准中被称为“通常的算术转换”。它如何适用于您的案例取决于您如何称呼
malloc。 (malloc(a+b)与c = a + b; malloc(c)不同,如果sizeof(c) < sizeof(int)。)遵循通常的算术转换规则,看看在这种情况下会发生什么。 -
malloc期待 64 位整数?不,它需要一个整数size_t。您真的应该在 C(或 C++?)中查找有关整数类型的基础知识,特别是如果类型是有符号或无符号的,溢出是完全不同的。 -
如果您发布代码,而不仅仅是代码描述,将会得到更好的答案。
标签: c++ c 32bit-64bit