Operating system while(1)无限循环和递归函数之间有什么区别?

Operating system while(1)无限循环和递归函数之间有什么区别?,operating-system,Operating System,操作系统中到底发生了什么?对于递归函数,堆栈可能溢出,而对于while(1)?如果我错了,请纠正我。递归函数有一个子句,它不调用自己,这意味着它结束。递归函数不断调用自己,而无限循环不断重复相同的代码块 调用函数时,必须保留一些存储以将其返回值存储在上。因此,如果函数的递归调用足够多,堆栈空间将耗尽,并导致堆栈溢出 考虑 #include <stdlib.h> #include <stdio.h> int somefunc(int x) { printf("%d

操作系统中到底发生了什么?对于递归函数,堆栈可能溢出,而对于while(1)?如果我错了,请纠正我。

递归函数有一个子句,它不调用自己,这意味着它结束。

递归函数不断调用自己,而无限循环不断重复相同的代码块

调用函数时,必须保留一些存储以将其返回值存储在上。因此,如果函数的递归调用足够多,堆栈空间将耗尽,并导致堆栈溢出

考虑

#include <stdlib.h>
#include <stdio.h>

int somefunc(int x) {
    printf("%d\n", x);
    return somefunc(rand());
}

int main(void) {
    return somefunc(0);
}

它将愉快地运行,直到用户终止为止(通过按CTRL-C或关闭计算机)。

递归函数将重复调用自身。无限循环只会重复执行相同的代码。虽然这听起来很相似,但实际效果却大不相同。每次调用方法时,都会将变量推送到堆栈上。当然,这意味着函数可以递归的次数存在固有的限制。因此,尽管无限循环将永远执行,但实际中的递归函数最终将耗尽堆栈空间,应用程序很可能会停止运行。

递归函数调用自身,将参数推送到堆栈上。这可能永远持续下去,最终导致堆栈溢出。一些编译器可以通过将递归函数转化为while循环来优化它,这称为尾部递归

while循环将简单地返回到顶部并再次重用相同的空间,这样它就可以永远运行(至少直到电源熄灭:-)

函数将堆栈上的return(调用下一个递归函数的内存中的位置)地址推到内存中的位置(到递归函数)。 while不需要存储ret地址,因为它只在开始处跳转。

在“while(1)”无限循环中,将为堆栈帧分配堆栈空间(关于函数返回时返回到何处的信息)并且,无论循环执行多少次迭代,在同一函数中声明的任何局部变量都将在堆栈上分配一次

因此,对于1000000次迭代, 堆栈空间应为sizeof(堆栈帧)+sizeof(任何局部变量)

因此,如果堆栈帧为16字节,int为4字节,则函数将在堆栈上分配20字节

然而,递归函数每次调用自身时都会在堆栈上为堆栈帧(关于要返回的函数的信息)和任何局部变量分配空间

因此,对于1000000次迭代, 堆栈空间为(sizeof(堆栈帧)+sizeof(任何局部变量))*100000


因此(使用以前的大小)20bytes*1000000==20000000bytes==(大约)19MB

递归函数可以结束,这取决于它的编码方式。当然,它不需要以堆栈溢出结束<代码>while(1)循环如果有中断或返回也可以结束。

调用函数时,堆栈上会为其分配一些内存。它保持: -传递给函数的参数值 -returnaddress—函数返回后执行的内存地址 -局部变量 -取决于实施的其他事项

所以递归函数中的每个函数调用都分配内存。所以在设计过程中你必须小心

在while(1)的情况下,执行程序的进程具有无限循环,如while(1){;}
只是重复部分命令。让这样的进程在操作系统中保持运行状态只需要CPU时间和一些内存。

对于简单代码和好的编译器来说没有区别,但是对于具有非终止递归函数的幼稚编译器,您将耗尽堆栈空间,称为堆栈溢出

至于发生了什么问题:在堆栈溢出中:堆栈映射到一个位置或内存(每个进程),旁边有未分配的内存。堆栈用于存储本地函数值,当前函数返回地址也放在堆栈上,然后将传递给下一个函数的值放在堆栈上。因此,每次函数调用都使用堆栈。因此,当CPU try的访问内存通过分配空间的末尾时,会导致内存访问异常,并将其解释为堆栈溢出

有一段时间(1)操作系统的行为取决于操作系统使用的多任务行为。对于先发制人的系统(例如Window NT和更新版本),它只会看到您的进程有很多工作要做,但是如果它有UI,并且您没有响应它发送给您的窗口消息,您将收到经典的“此应用程序似乎已停止响应”消息

如果您有一个非抢占式操作系统,那么它将挂起,如果您不将控制权交还给操作系统,那么在Windows 3.1中,打印机驱动程序将在打印时冻结整个系统。惠普的驱动程序做到了

在嵌入式系统上,为了避免软件锁定,它们通常有一个硬件计时器,称为看门狗计时器,如果不是每秒“嘀嗒”一声,就会重新启动系统。从而防止系统处于锁定状态

虽然(1)
不会创建新的计算上下文,但递归(除非编译器进行了优化)会创建新的计算上下文。这意味着几件事:

  • 在所有实际实现中,当无法创建新的计算上下文(即发生堆栈溢出)时,递归将达到极限
  • 新的计算上下文意味着您声明的任何局部变量的新副本
  • 使用一个简单的
    返回退出
    ,而(1)
    退出
    是很简单的,但是
    返回只在递归中退出当前上下文。完全退出多重嵌套上下文并不是那么简单
问题A
int somefunc(int x) {
    return printf("%d\n", x);
}

int main(void) {
    while ( 1 ) {
        somefunc(rand());
    }
    return 0;
}