简体   繁体   English

为什么C中的这个无限循环不会无限循环?

[英]Why does this infinite loop in C not loop infinitely?

I am running this below 'C' program which has an infinite loop. 我正在有无限循环的“ C”程序下运行此程序。 I see the CPU reaching almost 99% using the 'top' command. 我看到使用“ top”命令的CPU几乎达到了99%。 Then suddenly the program stops. 然后程序突然停止。 I was curious to know what rule in the system is causing it to stop. 我很想知道系统中有什么规则导致它停止。

I am running this under a docker image alpine:3.1 (+ some modules) and I just simply start its ash (alpine's bash). 我在docker image alpine:3.1(+一些模块)下运行它,我只是简单地启动它的ash(alpine的bash)。
Also, I can not find ulimit. 另外,我找不到ulimit。

#include <stdio.h>
int main() {
    int marks[10],i,n,sum=0;
    printf("Enter number of students: ");
    scanf("%d",&n);
    for(i = 0; i < n; --i) {
        //printf("Enter marks of student%d: ",i+1);
        int c;
        c = 5;
        int a;
        a = c;
    }
    return 0;
}

As you mention, you could expect this to produce an infinite loop, at least if n is positive. 正如您提到的,至少在n为正数的情况下,您可能会期望这会产生无限循环。

The behaviour you're seeing instead is caused by your counter wrapping around: when it reaches INT_MIN , the result of --i is INT_MAX (at least, with GCC's default settings on Intel-style CPUs — this is not defined in C, see below) and i<n fails. 你看到的,而不是行为是由周围的计数器归零造成的:当它到达INT_MIN ,结果--iINT_MAX (至少,对英特尔CPU的风格GCC的默认设置-这是不是在C定义,见下面),而i<n失败。

So your program uses 100% of one CPU while it counts down from 0 to INT_MIN , then wraps around to INT_MAX and stops. 因此,您的程序使用一个CPU的100%,同时它从0 INT_MININT_MIN ,然后回绕到INT_MAX并停止。

You can add 你可以加

printf("%d\n", i);

just before the return line to see the value of i when the loop exits. 刚好在return行之前,以查看循环退出时i的值。

Note that this is undefined behaviour in C ... If you compile this with -O2 , at least with GCC 5.3, the program never exits the loop, because the optimiser decides that the exit condition will never be reached, and compiles the loop as a tight infinite loop if n is positive ( .L4: jmp .L4 ). 请注意,这是C语言中未定义的行为 ...如果使用-O2编译,至少使用GCC 5.3编译,则程序永远不会退出循环,因为优化程序会确定永远不会达到退出条件,并将循环编译为如果n为正( .L4: jmp .L4 ), .L4: jmp .L4紧密的无限循环。

Your loop is not infinite per se. 您的循环本身并不是无限的。 YOu have a termnation condition which can be reached - in principle. 原则上可以达到终止条件。 The CPU load occurs, just because the loop runs for (likely) >2000000000 iterations before it ends. 发生CPU负载是因为循环在结束之前运行了(可能)> 2000000000次迭代。

First of all, you don't check the result of scanf . 首先,您无需检查scanf的结果。 If it failed, n is unspecified. 如果失败,则未指定n

Worse, your code invokes undefined behaviour (UB) due to signed integer over-/underflow. 更糟糕的是,由于带符号的整数上溢/下溢,您的代码调用了未定义的行为 (UB)。 You decrement i past the minimum representable int value INT_MIN . 您将i减小到最小可表示的intINT_MIN Note that C does not have arbitrary length integers like Python. 请注意,C没有像Python这样的任意长度的整数。

Undefined behaviour means anything can happen, all bets are off. 未定义的行为意味着任何事情都可能发生,所有赌注都没有了。 In your case, it might wrap to the max. 在您的情况下,它可能会最大化。 positive int INT_MAX , thus the comparison fails and the loop is exited. int INT_MAX ,因此比较失败,并且退出循环。 But this is nothing you can rely on! 但是,这是您不能依靠的!

From the text and rest of the code, you likely don't want to decrement i , but increment: i++ , so it counts from 0 to n - 1 . 从文本和代码的其余部分,您可能不想减少i ,而是增加: i++ ,所以它的计数从0n - 1 Note that you also should check n for a valid range and ask the use to enter a valid value again. 请注意,您还应该检查n的有效范围,并要求用途再次输入有效值。 For the example, a negative upper limit is useless (but it does also no harm). 例如,负的上限是没有用的(但也没有害处)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM