【问题标题】:Why does this supposedly infinite loop program terminate?为什么这个所谓的无限循环程序会终止?
【发布时间】:2020-04-15 04:57:22
【问题描述】:

我正在和我的朋友谈论这两段代码。他说 python 会终止,而 C++ 不会。

Python:

arr = [1, 2, 3]
for i in range(len(arr)):
  arr.append(i)
print("done")

C++:

#include <iostream>
#include <vector>
using namespace std;

int main() {
  vector<int> arr{1,2,3};
  for(int i = 0; i < arr.size(); i++){
    arr.push_back(i);
  }
  cout << "done" << endl;
  return 0;
}

我对此提出了质疑,并在 2 台计算机上运行了它。第一个内存不足(错误分配),因为它有 4gb 的内存。我的 mac 是 12gb 的 ram,它能够正常运行和终止。 我认为它不会永远运行,因为向量中的 size() 类型是无符号整数。由于我的 mac 是 64 位的,我认为它可以存储 2^(64-2)=2^62 个整数(这是真的),但由于某种原因,大小的无符号整数是 32。

这是 C++ 编译器中的一些错误,它不会将 max_size() 更改为相对于系统的硬件?溢出导致程序终止。还是其他原因?

【问题讨论】:

  • @Scheff: i &lt; arr.size()继续循环的条件,而不是停止循环的条件。
  • python版本预先计算range(len(arr))设置迭代次数,所以是有限的。 C++ 版本将一个元素附加到arr,因此arr.size() 会随着每次迭代而增加。因此,i 总是小于arr.size(),因此循环将继续进行(直到内存耗尽,或者i 溢出并导致未定义的行为,之后所有的赌注都被取消了)。在循环前引入size = arr.size()这样的新变量,将终止条件改为i &lt; size,循环将是有限的。
  • @user2357112supportsMonica 因此,我假设环绕 -> 负 int 隐式转换为 size_t(可能是无符号 64 位类型)导致终止。 Demo on coliru
  • @Scheff:似乎是一个可能的假设。
  • 这是 C++ 编译器中的一些错误吗 -- 如果 C++ 编译器在像这样的玩具程序中有这样的错误,他们可能会被嘲笑编译器业务。

标签: python c++ vector infinite-loop applicationwillterminate


【解决方案1】:

在您的 C++ 编译器中没有出现错误。

int 溢出(由于i++),其行为未定义。 (在此溢出发生之前,您可能会在某些平台上耗尽内存。)请注意,没有定义的行为会使 i 为负数,尽管这在具有 2 的补码有符号整数类型的机器上很常见达到std::numeric_limits&lt;int&gt;::max(),如果i 是-1,那么i &lt; arr.size() 将是false,因为i 隐式转换为unsigned 类型。

Python版本预计算range(len(arr));即后续追加不会更改该初始值。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-11-08
    • 2011-08-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-01-08
    相关资源
    最近更新 更多