int main(){
while(1)
{
//code
}
return 0;
}
这是一个无限循环,但是这会导致系统崩溃吗?
它的表现如何?
我认为它会吃掉所有堆栈段。
最佳答案
this is an infinite loop
是的。我注意到一个不错的现代 C 编译器会给你一个警告,顺便说一句。
but did this lead to a system crash?
不,不会。
如果它是一个用户态进程,它不会导致“系统”(内核)崩溃,因为它不会破坏或滥用内核资源。
您按原样发布的代码也不会导致进程崩溃,因为代码中也没有任何非法或未定义的内容(它不会做任何有用的事情)。
基本上,这个(如果编译时没有优化):
# 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
循环无关)
how does this behaves?
它会被编译成一个无限跳转的汇编代码中的普通无条件分支。 (它不会导致系统挂起,因为操作系统控制抢占式多任务中断计时器处理程序)。
I am thinking - it will eat up all the stack segment.
不会,因为您发布的代码不会递增堆栈指针(例如,通过在循环内分配堆栈上的任何内容而不递减堆栈指针,或者通过在循环内进行函数调用而不弹出被调用函数的框架 - 如果您使用错误的调用约定,这可能会发生,但这是一个高级主题)。
如果……怎么办?
如果你在 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;
}
(这也是为什么非常古老的编程语言经常让您在函数的开头声明所有局部变量,而不是允许在函数内部声明 - 他们不再这样做了,因为值得庆幸的是,语言设计者现在比现在更关心语言人机工程学他们曾经这样做过)。
...但是...
一般来说,永远不要在不调用 free()
的情况下调用 malloc()
(或者更一般地说:永远不要在不释放资源的情况下获取资源),所以这个 代码将导致您的程序耗尽内存最终:
while( 1 ) {
void* ptr = malloc( 1024 )
}
...但这不会:
while( 1 ) {
void* ptr = malloc( 1024 );
if( ptr ) free( ptr );
}
(好吧,它可能会耗尽内存 due to heap fragmentation,这取决于您的 malloc
实现有多好)
不要忘记递归
C 使得直接操作堆栈出奇地困难(例如,尾调用优化要求编译器将其作为优化处理:不幸的是,您不能使用 C 语言功能强制尾调用返回)-所以(据我所知)只有两种主要方法可以破坏堆栈:
溢出堆栈的主要方法是压入更多堆栈帧而不弹出它们 - 这可以通过无限递归函数调用(没有尾调用优化)来完成。
...或者通过做一些愚蠢和/或愚蠢的事情,例如通过使用 alloca
(类似于 malloc
,但在堆栈上分配内存:但不会告诉您是否失败)。
关于c - 无限循环会导致系统崩溃吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57851267/