Recursion and looping are techniques that can solve similar problems in different ways (as mentioned in the comments, they are Turing equivalent, but this is not my field).
Each function call adds a frame to the call stack. This requires additional memory and as your call chain goes deeper, it requires more memory until a certain limit is crossed, which makes your stack overflow
and your program to crash.
Your recursive code adds more and more frames to the call stack and, given finite amount of memory, will cause it to overflow. You need some way to tell the recursion when to stop, and do so before the memory is exhausted. Such condition is equivalent to the base case
in the mathematical induction, therefore it is usually referred to as such.
Another option, pointed in the comments, is utilizing Tail call optimizations, which replace the current frame in the stack and therefore may prevent the stack from overflowing.
Your iterative solution only requires a fixed amount of memory.
Only the value of a counter or other predefined variables is changed, therefore it does not incur any memory overhead.
If you do not limit the output, it could theoretically go on indefinitely, but some other exhaustion or error will most likely kill it. However, this will not be the memory consumed by the variables used in the loop itself.