无限循环和没有停止条件的递归函数何时最终停止?

发布于 2024-11-27 01:38:37 字数 238 浏览 0 评论 0原文

我听到一个神话说无限循环或没有停止条件的递归函数将在“堆栈溢出”时停止。对吗?

例如:

void call()
{
call(); 
} 

或者

for(;;){;}

当堆栈溢出时它们真的会停止吗?

更新:如果真的停止了,我可以检测到递归调用了多少次之后吗?

I heard a myth saying that infinite loop or a recursive function with no stop condition will stop when "the stack overflows". Is it right?

For example :

void call()
{
call(); 
} 

or

for(;;){;}

Will they really stop when the stack overflows?

Update: If it really stops, can I detect after how many recursive calls?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

信愁 2024-12-04 01:38:37

这实际上取决于语言的选择。

在某些语言中,无限递归函数将根据系统或语言相关条件因堆栈溢出而停止。原因是许多函数调用和返回的实现为每个函数调用分配新的空间,当空间耗尽时程序将失败。然而,其他语言(Scheme 和各种 gcc 优化级别)实际上会让这个程序永远运行,因为它们足够聪明,意识到它们可以为每个调用重用空间。

在某些语言中,无限循环将永远运行。你的程序只会继续运行,永远不会取得进展。在其他语言中,编译器允许优化掉无限循环。举个例子,C++ 标准规定编译器可以假设任何循环都会终止或执行一些全局可见的操作,因此如果编译器看到无限循环,它可能会优化该循环以使其不存在,因此循环实际上确实终止了。

换句话说,这确实取决于。这个问题没有硬性的答案。

希望这有帮助!

It really depends on the choice of language.

In some languages, your infinite recursive function will halt with a stack overflow based on system- or language-dependent conditions. The reason for this is that many implementations of function call and return allocate new space for each function call, and when space is exhausted the program will fail. However, other languages (Scheme and various gcc optimization levels) will actually have this program run forever because they are smart enough to realize that they can reuse the space for each call.

In some languages, infinite loops will run forever. Your program will just keep on running and never make progress. In other languages, infinite loops are allowed to be optimized away by the compiler. As an example, the C++ standard says that the compiler is allowed to assume that any loop will either terminate or make some globally-visible action, and so if the compiler sees the infinite loop it might just optimize the loop out of existence, so the loop actually does terminate.

In other words, it really depends. There are no hard-and-fast answers to this question.

Hope this helps!

披肩女神 2024-12-04 01:38:37

您的第一个示例是递归方法调用 - 每次调用 call (在大多数语言和环境中)都会创建一个新的堆栈框架,最终您将耗尽堆栈(您将得到一个堆栈溢出条件)。

您的第二个示例不涉及递归方法调用 - 它只是一个循环。不需要创建栈帧,栈也不会溢出。

尝试一下您的示例 - 第一个示例导致堆栈溢出的速度比您想象的要快。第二个会让你的风扇旋转得非常快,但在你杀死它之前什么也不会发生。

Your first example is a recursive method call - each invocation of call (in most languages and environments) will create a new stack frame, and eventually you'll run out of stack (you'll get a stack overflow condition).

Your second example involves no recursive method invocation - it's just a loop. No stack frames need to be created, and the stack won't overflow.

Give your examples a shot - the first example will cause a stack overflow faster than you may think. The second will make your fans spin really fast, but nothing will happen otherwise until you kill it.

墟烟 2024-12-04 01:38:37

根据您使用的语言,循环将在达到最大分配内存或最大执行时间时结束。有些语言会检测到无限循环并阻止其运行。

ps 这不是神话。你其实可以尝试一下。

Depends on which language you are using, the loop will end when maximum memory allocated or max execution time is reached. Some languages will detect infinite loop and stop it from running.

p.s. It is not a myth. You can actually try it.

·深蓝 2024-12-04 01:38:37

“更新:如果真的停止了,我可以在递归调用多少次后检测到吗?”

您当然可以:

call(int n){
    print(n)
    call (n+1)
}

然后只需调用:

call(1)

当堆栈溢出发生时,查看最后打印的数字。这是您的方法调用次数。

希望这有帮助!
NS

"Update: If it really stops, can I detect after how many recursive calls?"

You most certainly can:

call(int n){
    print(n)
    call (n+1)
}

Then just call:

call(1)

When the stack overflow occurs, look at the last printed number. This was the number of method calls you had.

Hope this helps!
N.S.

〆一缕阳光ご 2024-12-04 01:38:37

无论使用哪种语言,当我创建一个可能无限的循环时,我总是在其中构建一个“紧急出口”。我已经在 C#、VB.Net、VBA、JAVA 中完成了此操作,而现在是第一次在 IBM DB2 SQL 函数中完成此操作。

由于这个概念在任何语言中都有效,因此我将以伪代码的形式呈现它,如下所示:

Begin Procedure

Declare Variable safety_counter As Integer

Begin loop
    ...
    <body of code>
    If some_criteria = True Then          <-- this is your normal exit
        Exit Loop
    End If
    ...
    safety_counter = safety_counter + 1
    If safety_counter >= 1000             <-- set to any value you wish
        Exit Loop                         <-- this is the emergency exit
    End If
End Loop

一些变体如下。

如果循环比较简单,两个退出条件可能会写在同一个 If-Then 中:

    If some_criteria = True Then          <-- normal exit
    Or safety_counter >= 1000             <-- emergency exit
        Exit Loop
    End If
    safety_counter = safety_counter + 1

可能会返回一个错误值,如下所示:

Begin Procedure

Declare Variable result_value   As Integer
Declare Variable safety_counter As Integer

Begin loop
    ...
    <body of code>
    If some_criteria = True Then          <-- this is your normal exit
        Set result_value = abc * xyz      <-- the value you seek          
        Exit Loop
    End If
    ...
    safety_counter = safety_counter + 1
    If safety_counter >= 1000             <-- set to any sufficient value
        Set result_value = (-123)         <-- indicate "infinite loop error"
        Exit Loop                         <-- this is the emergency exit
    End If
End Loop
Return result_value

可能的方法有很多种,但关键在于 safety_counter 以及监控的方式它触发紧急出口。

No matter the language, when I create a loop that is potentially infinite, I always build an "emergency exit" into it. I've done this in C#, VB.Net, VBA, JAVA, and just now for the first time in an IBM DB2 SQL function.

Since the concept is valid in any language, I'll present it in pseudocode, as follows:

Begin Procedure

Declare Variable safety_counter As Integer

Begin loop
    ...
    <body of code>
    If some_criteria = True Then          <-- this is your normal exit
        Exit Loop
    End If
    ...
    safety_counter = safety_counter + 1
    If safety_counter >= 1000             <-- set to any value you wish
        Exit Loop                         <-- this is the emergency exit
    End If
End Loop

Some variations are as follows.

If the loop is simple, the two exit criteria might be written in the same If-Then:

    If some_criteria = True Then          <-- normal exit
    Or safety_counter >= 1000             <-- emergency exit
        Exit Loop
    End If
    safety_counter = safety_counter + 1

An error value might be returned like this:

Begin Procedure

Declare Variable result_value   As Integer
Declare Variable safety_counter As Integer

Begin loop
    ...
    <body of code>
    If some_criteria = True Then          <-- this is your normal exit
        Set result_value = abc * xyz      <-- the value you seek          
        Exit Loop
    End If
    ...
    safety_counter = safety_counter + 1
    If safety_counter >= 1000             <-- set to any sufficient value
        Set result_value = (-123)         <-- indicate "infinite loop error"
        Exit Loop                         <-- this is the emergency exit
    End If
End Loop
Return result_value

There are many possible ways to do this, but the key is in safety_counter, and the way of monitoring it to trigger the emergency exit.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文