what is the difference between while(1) infinite loop and a recursive function?
what h开发者_运维技巧appens in the operating system exactly? for a recursive function mayb a stack overflow and for while(1)? please correct me if im wrong?
A recursive function will call itself repeatedly. The infinite loop will just keep executing the same code repeatedly. While this may sound very similar, the actual effects are very different. Each time a method is called, variables are pushed onto the stack. Of course, this means that there are inherent limits to the number of times a function can recurse. So while your infinite loop will execute forever, a recursive function in practice will eventually run out of stack space and the application will likely come to a grinding halt.
A recursive function calls itself, which pushes parameters onto the stack. This may go on forever, eventually leading to a stack overflow. Some compilers can optimize this away essentially turning the recursive function into a while loop -- this is called tail recursion.
The while loop will simply go back to the top and reuse the same space over again, so it can run literally forever (at least until the power goes out :-))
A recursive function keeps calling itself whereas an infinite loop keeps repeating the same block of code.
When a function is called, some storage must be reserved to store its return value on the function call stack. So, given enough recursive invocations of the function, the stack space will be exhausted and cause a stack overflow.
Consider
#include <stdlib.h>
#include <stdio.h>
int somefunc(int x) {
printf("%d\n", x);
return somefunc(rand());
}
int main(void) {
return somefunc(0);
}
The program above will eventually terminate or do some serious damage as opposed to
int somefunc(int x) {
return printf("%d\n", x);
}
int main(void) {
while ( 1 ) {
somefunc(rand());
}
return 0;
}
which will happily run until the user causes termination (by pressing CTRL-C or turning off the computer.)
A recursive function can end depending how it is coded. Of course, it does not need to end with a stack overflow. while(1)
loop also can end if it has breaks or return.
A recursive function has a clause where it doesn't call itself, meaning it ends.
In a 'while(1)' infinite loop, will allocate stack space for a stack frame (information about where to return to if/when the function returns) and any local variables that are declared in the same function will be allocated once on the stack regardless of how many iterations the loop executes.
Therefore, for 1000000 iterations, stack space would be sizeof(stack frame) + sizeof(any local variables)
so if stack frame is 16bytes and int is 4bytes, the function would allocate 20bytes on the stack.
Whereas, a recursive function will allocate space on the stack for a stack frame (information about the function to return to) and any local variables each time the function calls itself.
Therefore, for 1000000 iterations, stack space would be (sizeof(stack frame) + sizeof(any local variables)) * 100000
so (using previous sizes) 20bytes * 1000000 == 20000000bytes == (approx) 19MB
function pushes return (The place in memory from where next recursive function has been invoked) address on stack and jumps to the place in memory (to the recursive func). And while doesn't need to store ret address because it only jumps on the beginning.
When function is called, some memory on stack is allocated for it. It keeps : - parameter values passed to a function - return address - address in memory where execution will go after function return - local variables - other things that depend on implementation
So every function call in recursive function allocates memory. So you have to be careful during design.
In case of while(1) - process which executes program with infinite loop like while(1){;} just repeats some part of commands. Keeping such process in running state in operating system which just takes CPU time and some memory.
For simple code and a good compiler there is no difference, but for a naive compiler with a non-terminating recursive function, you will run out of stack space, called a stack overflow.
As to the what happens questions: in a stack overflow: the stack is mapped to a location or memory (per process) that has non allocated memory next to it. The stack is used to store local function values, the current function return address is also put on the stack, and then values been passed to next function are placed on the stack. Thus consuming the stack for each function call. So when the CPU try's access memory pass the end of the allocate space, thus causes a memory access exception, and it is interpreted as a stack-overflow.
For a while(1) the operating system behaviour depends what multitasking behaviour you OS uses. For a pre-emptive system (eg Window NT and newer), it just sees that your process has lots of work to-do, but if it has UI and you don't respond to the windowing messages it send you, you'll get the classic "This application appears to have stopped responding" message.
Where-as if you have a non-pre-emptive OS then it will hang, if you don't hand back control to the OS, thus in Windows 3.1 days, the printer driver would freeze the whole system while printing. Well the HP drivers did.
On embedded system to avoid the software locking up, they usually have a hardware timer called a watchdog timer, that if not 'tickled' every second, will reboot the system. Thus preventing the system staying in a locked-up state.
while (1)
doesn't create a new evaluation context, recursion (unless optimized away by the compiler) does. This means several things:
- In all practical implementation, the recursion will hit a limit when a new evaluation context can not be created (i.e. a stack overflow occurs).
- New evaluation context means new copies of any local variables that you declare.
- It's trivial to exit out of a
while (1)
with one simplereturn
, but areturn
only exits the current context in a recursion. It's not as trivial to completely exit out of multiply nested contexts.
精彩评论