Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/64.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 无限while循环是否会导致系统崩溃?_C_While Loop_Infinite Loop - Fatal编程技术网

C 无限while循环是否会导致系统崩溃?

C 无限while循环是否会导致系统崩溃?,c,while-loop,infinite-loop,C,While Loop,Infinite Loop,这是一个无限循环,但这会导致系统崩溃吗? 它的行为如何? 我想它会吃掉所有的堆栈段 这是一个无限循环 是的。我注意到一个体面的现代C编译器会给你一个警告,顺便说一句 但这是否导致了系统崩溃 不,不会的 如果它是一个userland进程,它不会导致“系统”(内核)崩溃,因为它不会损坏或滥用内核资源 您发布的代码也不会导致进程崩溃,因为代码中也没有非法或未定义的内容(它只是不会做任何有用的事情) 基本上,这(如果编译时未进行优化): 您可以使用诸如godbolt.org之类的编译器输出资源管理器站点

这是一个无限循环,但这会导致系统崩溃吗?
它的行为如何?
我想它会吃掉所有的堆栈段

这是一个无限循环

是的。我注意到一个体面的现代C编译器会给你一个警告,顺便说一句

但这是否导致了系统崩溃

不,不会的

如果它是一个userland进程,它不会导致“系统”(内核)崩溃,因为它不会损坏或滥用内核资源

您发布的代码也不会导致进程崩溃,因为代码中也没有非法或未定义的内容(它只是不会做任何有用的事情)

基本上,这(如果编译时未进行优化):

您可以使用诸如godbolt.org之类的编译器输出资源管理器站点亲自看到这一点:-注意堆栈指针没有变化(在
rsp
-忽略函数序言中的
mov
,这与
while
循环无关)

这是怎么回事

它将被编译成汇编代码中的一个微不足道的无条件分支,并无限跳跃。(这不会导致系统挂起,因为操作系统控制抢占式多任务中断计时器处理程序)

我在想——它会吃掉所有堆栈段

不会,因为您发布的代码没有增加堆栈指针(例如,通过在循环内的堆栈上分配任何内容而不减少堆栈指针,或者通过在循环内进行函数调用而不弹出被调用函数的帧-如果使用错误的调用约定,可能会发生这种情况,但这是一个高级主题)

如果…怎么办。。。? 如果在while循环中有一个局部变量,这实际上不会导致每次迭代的分配,因为上一次迭代的值不再可访问-因此

#    Instruction
1    main:
2        push rbp        ; `int main` function prologue
3        mov  rbp, rsp   ;
4    .loop:
5        jmp  .loop      ; Jump to right before this instruction
…相当于:

while( 1 ) {
    int foo;
    int ok = fscanf( fd, "%d", &foo );
    if( !ok ) break;
}
(这也是为什么非常古老的编程语言经常让您在函数开始时声明所有局部变量,而不是允许在函数内部声明-它们不再允许了,因为谢天谢地,语言设计师现在比过去更关心语言工效学)

但是 一般来说,如果不调用
free()
,就不要调用
malloc()
(或者更一般地说:如果不释放资源,就不要获取资源),因此此代码最终会导致程序内存不足:

…但这不会:

while( 1 ) {
    void* ptr = malloc( 1024 )
}
(好吧,它可能会耗尽内存,这取决于
malloc
实现的好坏)

别忘了递归 C使直接操作堆栈变得异常困难(例如,尾部调用优化要求编译器将其作为优化处理:不幸的是,不能使用C语言功能强制尾部调用返回)-因此(据我所知),只有两种主要方法可以破坏堆栈:

溢出堆栈的主要方法是在不弹出堆栈帧的情况下推送更多的堆栈帧——这可以通过无限递归函数调用(无需尾部调用优化)来实现


…或者做一些愚蠢和/或愚蠢的事情,例如使用
alloca
(如
malloc
,但在堆栈上分配内存:但不告诉您是否失败)。

这是循环的asm代码。它只跳到上一行代码

while( 1 ) {
    void* ptr = malloc( 1024 );
    if( ptr ) free( ptr );
}

这段代码不需要任何内存。简短回答:不,这绝对不会导致系统崩溃

有两个较长的答案:

(1) 这个程序是一个直接的无限循环。它会使处理器尽可能地工作,什么也不做。因此,是的,处理器会努力工作——但不会中断,因为它没有做任何“错误”的事情,也没有任何东西会耗尽或磨损

想象你有一辆非常漂亮的车。一辆神奇的漂亮车。想象它可以达到150英里/小时,每加仑汽油可以行驶无限英里,这样它就永远不会耗尽燃料。现在想象你有一条无限长、完美笔直的路。你开着这辆完美的车走上完美的道路,然后踩下它,很快你就要出发了时速150英里,你想干多久就干多久——因为,什么能阻止你

现在,在现实世界中,当然,没有一辆汽车是那么完美:除了燃料,所有真正的汽车都需要定期润滑和其他维护,它们最终会磨损。但我不认为将计算机视为一台完美的机器是错误的:坐在那里,尽其所能地努力工作,基本上永远都是非常愉快的

(事实并非如此。在现实世界中,计算机和汽车一样,最终也会磨损。如果计算机被超频,或者如果有人偷懒,没有在CPU上安装足够大的散热片,那么像这样全速运行可能会导致其发热并缩短其寿命。但这并不是真正的问题“系统崩溃”是我们在这里讨论的话题。)

(二)另一个答案是,即使像这样的无限循环程序做了一些错误的事情,比如试图无限次调用递归函数,或者分配无限量的内存,或者打开无限数量的文件——即使在这种情况下,一个行为不好的程序也不应该使整个系统崩溃。程序可能会崩溃,但系统不会

操作系统的主要职责之一是确保普通的应用程序不会相互干扰,也不会干扰操作系统本身。如果普通的应用程序会使整个系统崩溃,那么操作系统中就有一个严重的错误——一个严重的错误

现在,在协作多任务的糟糕年代,这是不正确的,在微软Windows的糟糕年代,这是不正确的(蓝屏死亡是司空见惯的)。如果你在做嵌入式编程,这也是不正确的。但是在
while( 1 ) {
    void* ptr = malloc( 1024 )
}
while( 1 ) {
    void* ptr = malloc( 1024 );
    if( ptr ) free( ptr );
}
.L2:
    jmp .L2