allocating local variables that are too large to fit on the stack, for example an array with a million elements on a 64K stack.
too deep a call stack, even without recursion, if each routine has many local variables. example:
a() calls b() calls c()...calls z() calls a1()... calls z99().
Each routines local variable as well as a return address for each function (and maybe a stack smashing protector) stays on the stack, until the stack unwinds as each function exits.