这是一个无限循环
它是。 我注意到,一个不错的现代C编译器会警告您,顺便说一句。
但这是否导致系统崩溃?
不,不会。
如果它是一个用户级进程,则不会导致“系统”(内核)崩溃,因为它不会损坏或滥用内核资源。
按原样发布的代码也不会导致进程崩溃,因为代码中也没有非法或未定义的东西(它只会做任何有用的事情)。
基本上,这(如果未经优化而编译):
# 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
您可以使用类似于Godbolt.org的编译器输出资源管理器网站来亲自查看以下内容: https ://godbolt.org/z/BMzh7i-注意堆栈指针没有更改(在rsp -忽略函数序言中的mov ,与while循环无关)
这是如何表现的?
它会在汇编代码中编译为无级跳转的琐碎无条件分支。 (因为操作系统控制抢占式多任务中断计时器处理程序,所以不会导致系统挂起)。
我在想-它会耗尽所有堆栈部分。
这不是因为您发布的代码不会增加堆栈指针(例如,通过在循环内的堆栈上分配任何内容而不减少堆栈指针,或者通过在循环内进行函数调用而不弹出被调用函数的框架) -如果您使用了错误的呼叫约定, 可能会发生这种情况,但这是高级话题。
如果...?
如果在while循环中有一个局部变量,则实际上不会导致为每个迭代分配资源,因为以前的迭代值不再可用-因此...
while( 1 ) {
int foo;
int ok = fscanf( fd, "%d", &foo );
if( !ok ) break;
}
...相当于:
int foo;
int ok;
while( 1 ) {
ok = fscanf( fd, "%d", &foo );
if( !ok ) break;
}
(这也是为什么很老的编程语言经常让您在函数开始时声明所有局部变量,而不是允许在函数内部进行声明的原因-它们不再存在了,因为值得庆幸的是,语言设计人员现在比以前更关心语言人机工程学)。
...但...
一般来说,永远不会调用malloc()没有调用free() (或者更一般地说:从未获取资源而不释放它们),所以这段代码会导致程序运行出最后的记忆:
while( 1 ) {
void* ptr = malloc( 1024 )
}
...但这不会:
while( 1 ) {
void* ptr = malloc( 1024 );
if( ptr ) free( ptr );
}
(好吧, 由于堆碎片 ,它可能会耗尽内存,具体取决于您的malloc实现的情况)
不要忘记递归
C使得直接操作堆栈变得异常困难(例如,尾调用优化要求编译器将其作为优化来处理:不幸的是,您不能使用C语言功能强制执行尾调用返回)-因此(据我所知),只有两种主要方法可以解决问题:
溢出堆栈的主要方法是推入更多的堆栈帧而不弹出它们-这可以通过进行无限递归的函数调用来实现(无需尾调用优化)。
...或者通过做一些愚蠢和/或愚蠢的事情,例如通过使用alloca (例如malloc ,但是在堆栈上分配内存:但不会告诉您它是否失败)。