c++ - 当 32 位整数在 64 位机器上溢出时会发生什么?

标签 c++ c 32bit-64bit

情况如下:

  1. 一个 32 位整数溢出
  2. malloc,期望一个 64 位整数使用这个整数作为输入

现在在 64 位机器上,哪个语句是正确的(如果有的话):

假设有符号二进制整数 11111111001101100000101011001000 由于溢出而只是负数。这是一个实际存在的问题,因为您可能希望分配比 32 位整数所能描述的更多的字节。但随后它会以 64 位整数的形式读入。

  1. Malloc 将其读取为 64 位整数,发现 11111111001101100000101011001000########################## ##### 其中 # 是通配符位,表示存储在原始整数之后的任何数据。换句话说,它读取的结果接近其最大值 2^64 并尝试分配一些 quintillion 字节。它失败了。
  2. Malloc 将其读取为 64 位整数,转换为 0000000000000000000000000000000011111111001101100000101011001000,可能是因为它是如何加载到寄存器中的,留下很多位为零。它不会失败,而是分配负内存,就像读取正的无符号值一样。
  3. Malloc 将其读取为 64 位整数,并转换为 ########################## #####11111111001101100000101011001000,可能是因为它是如何加载到寄存器中的 # 通配符表示寄存器中先前存在的任何数据。根据最后一个值,它会非常不可预测地失败。
  4. 整数根本不会溢出,因为即使它是 32 位,它仍然在 64 位寄存器中,因此 malloc 可以正常工作。

我实际上对此进行了测试,导致 malloc 失败(这意味着 1 或 3 是正确的)。我认为 1 是最合乎逻辑的答案。我也知道解决方法(使用 size_t 作为输入而不是 int)。

我真的很想知道实际发生了什么。出于某种原因,我没有找到任何关于如何在 64 位机器上实际处理 32 位整数以应对这种意外的“强制转换”的任何说明。我什至不确定它是否在寄存器中真的很重要。

最佳答案

您的推理问题在于,它首先假设整数溢出将导致确定性和可预测的操作。

不幸的是,情况并非如此:未定义的行为意味着任何事情都可能发生,尤其是编译器可能会像永远不会发生一样进行优化

因此,如果发生这种可能的溢出,几乎无法预测编译器会生成什么样的程序。

  • 一个可能的输出是编译器忽略了分配,因为它不可能发生
  • 可能的输出是结果值是 0 扩展或符号扩展(取决于它是否已知为正)并解释为无符号整数。您可能会得到从 0size_t(-1) 的任何内容,因此可能分配的内存太少或太多,甚至无法分配,...
  • ...

未定义的行为 => 所有赌注都关闭

关于c++ - 当 32 位整数在 64 位机器上溢出时会发生什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22714760/

相关文章:

c++ - 将STL函数与结构一起使用?

c++ - 如何将 CMake 参数转发到 ExternalProject

c - 如何使用SCons分两步编译?

C - 字符连接到字符串

c - C 中的垂直翻转位图不起作用

python - 强制使用 python mmap 进行 32 位访问?

c++ - ImageMagick 使用 qt ans magick++ 打开和写入图像

c++ - 使用 unordered_set 时结构中嵌套结构的哈希函数

c# - 为什么 Math.Exp 在 32 位和 64 位之间给出不同的结果,具有相同的输入,相同的硬件

java - 64 位系统上 Java 的串行通信 API(调制解调器交互)