【问题标题】:why infinite loop terminates? or go infinite为什么无限循环终止?或无限
【发布时间】:2022-02-25 01:15:01
【问题描述】:

我正在尝试一个测试并且我编写了这个程序......

#include<iostream>
using namespace std;
main()
{
    int arr[5]={1,2,3,5,3}, num=5;
    for(int i=0; i< num; i++)
    {
        for(int j=(i+1); i< num; j++)
        {
            if (arr[i]==arr[j])
            {
                cout<<"test";
            }
            cout<<j<<endl;
        }
    }
}

嗯... 在下面的代码中,我知道我使用了“i”而不是“j”,所以只是为了创建问题,我使用了这个

for(int j=(i+1); i< num; j++)

而我的程序有问题的部分是-

for(int j=(i+1); i< num; j++)
        {
            if (arr[i]==arr[j])
            {
                cout<<"test";
            }
            cout<<j<<endl;
        }

在上面的代码中,当我删除这个 if 块时-

if (arr[i]==arr[j])
            {
                cout<<"test";
            }

程序无限运行...... 但是当我再次放置这个 if 块时,程序在执行一些操作后会自动终止。 I also read about this on this link but it shows example of java

它们显示了负值的原因,但是在我的程序中没有垃圾值来。

【问题讨论】:

  • main() --> int main()
  • 您正在描述您正在做的事情(添加了这个,删除了那个等),而不是完整地发布实际的新代码,这会导致问题。发布minimal reproducible example 的想法是,我们不必跟随尝试模仿您的描述,并得到我们写错的东西。
  • j 迟早会超出您的数组范围,从而导致未定义的行为。未定义的行为可能(但不是必须)导致崩溃。并且崩溃会使操作系统终止程序。
  • 你说的“程序在执行一些操作后会自动终止”是什么意思 循环后的代码会被执行吗?没有错误信息吗?返回码是成功还是错误?
  • @eerorika 没有错误信息出现,它只打印 j 值。

标签: c++


【解决方案1】:

循环条件永远不会为假。因此程序将无限期地继续运行。

但是,使用if (arr[i]==arr[j]),您可以在arr 的范围之外访问。因此程序的行为是未定义的。当程序的行为未定义时,它的行为不一定像您预期的那样。例如,它可能不会无限期地继续运行。

即使没有if (arr[i]==arr[j]),当循环计数器溢出时,循环最终也会有未定义的行为。但是具有未定义行为的程序不一定会像您预期的那样运行。例如,它可能会无限期地继续运行。

【讨论】:

    【解决方案2】:

    没有if (arr[i]==arr[j]),你只会有一个无限循环,这在这种情况下是完全有效的。 j 只会不断增加(最终这会溢出,在未定义的行为中,请参阅 [basic.fundamental]/2),并且永远不会满足条件,因为 i 不会改变。

    但是,使用代码中的if (arr[i]==arr[j])j 正在递增,您将超出数组的边界(如您所知)。在 C++ 中,这是未定义的行为,这意味着 任何事情 都可能发生。在您的情况下,它似乎导致程序崩溃(这实际上是一件好事,因为它表示错误)。

    【讨论】:

      【解决方案3】:

      我认为,代码的问题部分是

      for(int j=(i+1); i< num; j++)
      

      当您检查i&lt; num 时,您正在增加j

      如果你把它替换为

      for(int j=(i+1); j < num; j++)
      

      它可能会开始工作。

      为什么它以 if 块终止,而没有 if 块则不终止

      if (arr[i]==arr[j])
      {
        cout<<"test";
      }
      

      因为int 的可能值数量有限。当您达到int 变量的最大值时,value + 1 是可能的最小int。 (正如@user17732522 指出的那样,行为可能完全不同——程序崩溃或这里发生了一些令人讨厌的事情——因为int'溢出'的行为是未定义的。因此你的程序内存可能已经在这里损坏了,它需要执行一些操作看到它发生...例如通过程序崩溃。)

      现在,让我们想想arr[i] 做了什么。 arr 基本上是一个指向内存的指针,数组从这里开始,[i] 操作与*(arr + i) 是一回事。

      现在有两种可能发生的情况

      • i 为正且在数组之外时程序崩溃
      • i 为负数时程序崩溃

      在这两种情况下,程序都会崩溃,因为您试图访问内存的受保护区域或不存在的区域。这取决于系统的架构 - 例如。在 64 位 AMD64 系统的负区中,如果您没有 16 EB 的 RAM,您显然正在访问不存在的内存。在这种情况下,程序必须导致处理器中断,这会提供给您的操作系统,从而杀死您的应用程序。

      为什么删除块时它不会崩溃?没有人试图访问 *(arr + j),因此,j 正在从最小可能值重复到最大可能值,没有任何问题。

      【讨论】:

      • 我知道这一点。但是为什么它以 if 块终止,而不是在没有 if 块的情况下终止。
      • @kNIG132103 我添加了一个关于终止的新答案。
      • @user17732522 这对我来说听起来很奇怪。你能做一些参考吗? - 我从来没有在 amd64 或 x86 之外的其他架构上编程过,但我只是不想相信,这种行为通常不能使用 int。
      • @user17732522 好的。我现在相信你了。我将编辑答案。 -“溢出”int 是我最喜欢的错误,所以我知道它在调试器中的样子。但事实是,我从未将它用作程序的预期部分,所以我从未尝试过优化它……对于二进制操作,我总是使用无符号类型
      • @user17732522 现在更有意义了吗?
      【解决方案4】:

      问题是这个 if 语句永远为真:

      for(int j=(i+1); i< num; j++){infinity}
      

      尝试将其设置为:

      for(int j=(i+1); j< num; j++){not infinity}
      

      您不能在最终不会返回 false 或将永远持续下去的语句上传递循环。

      【讨论】:

      • 我知道这一点。但是为什么它以 if 块终止,而不是在没有 if 块的情况下终止。
      • 我认为这与调试控制台不想无限写行有关。我敢肯定,它会在写了这么多行之后终止。
      • 控制台不是这样工作的。
      猜你喜欢
      • 2021-06-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-11-12
      • 2010-10-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多