Will recursive function throw StackOverflowError - function

I have a code that calls itself (java) ..when it does not get some values.
public void recfunction() {
---do something----
if not found a then
call recFunction();
if found a save a and then exit the function.
}
recfunction can be called at most 5 times within itself. I get the value of "a" within 5 times. Will I get a StackOverflowError if I run this function 1000 times.
Edit: What I am trying to ask is when the function exits...will the Stack frames for all the calls be removed.

you can try it and find out, but no, as long as it is executing actual code and stays within stack limits it will not. stack size in java is 400k so as long as you're not tracking tons of varas on each call you should be fine.
If it only runs 5 times before throwing a stackoverflowerror, it's because you exceeded your stack.

The specific answer to your question is, "it depends."
But in general, yes, a recursive function that runs amok can cause a stack overflow error.
Particularly in Java, you have some control of stack size. So you can start the JVM with a smaller or larger stack, which will obviously impact how much stack there is to overflow.
Also, the amount of local storage you allocate in the function will contribute. If your function doesn't use any stack at all - just calls itself and maybe decrements a counter - you will have to use up the stack with only return address pointers and basic stack frame data.
But if you allocate a 1000-element array of objects in each local stack frame, then obviously you will consume more stack "per call", and thus you can overflow the stack in fewer levels of recursion.

Firstly, that code clearly won't compile, let alone run...
Secondly, assuming it did compile you could compile it and run it.
Most importantly, if you were to run it on multiple configurations you would discover different answers. See this question for example:
java -Xss4m Test
This will increase the stack size to four megabytes.

Related

Stack bounds checking on the Amiga 500

I have a 68000 assembly language program running on my Commodore Amiga 500 that could potentially use a lot of stack space, so I want to do bounds checking.
If I call FindTask(NULL), and check tc_SPUpper and tc_SPLower, I get $c22c24 and $c21fa4, which is 3200 bytes of stack; however, the CLI has 8000 bytes of stack allocated, and the program starts with a stack pointer of $c29598—about 26K higher in memory than tc_SPUpper.
I read in the AmigaDOS Developer's Manual that, on start, 4(sp) contains the stack size. This value does contain 8000. ("Below this on the stack at 4(SP) is the size of the stack in bytes, which may be useful if you wish to perform stack checking.")
Can I safely take sp - 4(sp) as the lower limit of the stack? Do I need to allow for the stack size, the return address, and some other data that the CLI may have on the stack?
After re-re-(…)-reading the manuals, I may have figured it out.
From Amiga ROM Kernel Reference Manual: Libraries & Devices, p.584:
The CLI does not create a new process for a program; it jumps to the
program's code and the program shares the process with the CLI.
From this, I gather that the process returned by FindTask(NULL) is the CLI process, and tc_SPUpper and tc_SPLower refer to the stack for that process.
From AmigaDOS Developer's Manual, p. 160:
When the CLI starts up a program, it allocates a stack for that
program. This stack is initially 4000 bytes, but you may change the
stack size with the STACK command. AmigaDOS obtains this stack from
the general free memory heap just before you run the program; it is
not, however, the same as the stack that the CLI uses.
From this, I conclude that my program stack is separate from the stack in the task returned by FindTask(NULL).
Also from AmigaDOS Developer's Manual, p. 160:
AmigaDOS pushes a suitable return address onto the stack that tells
the CLI to regain control and unload your program. Below this on the
stack at 4(SP) is the size of the stack in bytes…
From this, I conclude that, for programs run from the CLI, the following code will give me the lowest address available on the stack.
move.l sp,d0 ; current stack pointer
addq.l #8,d0 ; return address and stack size
sub.l 4(sp),d0 ; size of stack
move.l d0,stack_lowest ; save for stack checking
For programs launched from Workbench, I think tc_SPUpper and tc_SPLower are the values that I want.
From Amiga ROM Kernel Reference Manual: Libraries & Devices, p.584:
When a user activates a tool or project, Workbench runs a program.
This program is a separate process and runs asynchronously to
Workbench.
I have confirmed that the difference between these two values is, indeed, the stack size specified in the .info file.

Function call and context save to stack

I am very interested in real time operating systems for micro-controllers, so I am doing a deep research on the topic. At the high level I understand all the general mechanisms of an OS.
In order to better learn it I decided to write a very simple kernel that does nothing but the context switch. This raised a lot of additional - practical questions to me. I was able to cope with many of them but I am still in doubt with the main thing - Saving context (all the CPU registers, and stack pointer) of a current task and restore context of a new task.
In general, OS use some function (lets say OSContextSwitch()) that preserves all the actions for the context switch. The body of the OSContextSwitch() is mainly written in assembly (inline assembly in C body function). But when the OSContextSwitch() is called by the scheduler, as far as I know, on a function call some of the CPU registers are preserved on the stack by the compiler (actually by the code generated by the compiler).
Finally, the question is: How to know which of the CPU registers are already preserved by the compiler to the stack so I can preserve the rest ? If I preserved all the registers regardless of the compiler behaviour, obviously there will be some stack leakage.
Such function should be written either as pure assembly (so NOT an assembly block inside a C function) or as a "naked" C function with nothing more than assembly block. Doing anything in between is a straight road to messing things up.
As for the registers which you should save - generally you need to know the ABI for your platform, which says that some registers are saved by caller and some should be saved by callee - you generally need to save/restore only the ones which are normally saved by callee. If you save all of them nothing wrong will happen - your code will only be slightly slower and use a little more RAM, but this will be a good place to start.
Here's a typical context switch implementation for ARM Cortex-M microcontrollers - https://github.com/DISTORTEC/distortos/blob/master/source/architecture/ARM/ARMv6-M-ARMv7-M/ARMv6-M-ARMv7-M-PendSV_Handler.cpp#L76

How is the stack and link register used in an interrupt procedure? (ARM Processor)

The ARM website says that the link register stores the return information for subroutines, function calls, and exceptions (such as interrupts), so what is the stack used for?
The answers to this similar question say that the stack is used to store the return address, and to "push" on local variables that will need to be put back on the core registers after the exception.
But this is what the link register is for, so is why is it needed? What is the difference between the two and how are they both used?
Okay I think I understand your question.
So you have some code in a function call a function
main ()
{
int a,b;
a = myfun0();
b=a+7;
...
So when we call myfun0() the link register basically gets us back so we can do the b = a+7; understanding of course all of this gets compiled to assembly and optimized and such, but this will suffice to understand that the link register is used to return back to just after the call.
But what if
myfun0 ()
{
return(myfun1()+3);
}
when main calls myfun0() the link register points at some code in the main() function it needs to return to. then myfun0() calls myfun1() it needs to come back to myfun0() to do some more math before returning to main(), so when it calls myfun1() the link register is set to come back and add 3. the problem is when we set the link register to return to myfun0() we trash the address in main() we needed to return to. so to prevent that IF the function is going to call another function then as well as local variables that cant all live within the disposable registers the link register must be put on the stack. So now main calls myfun0(), myfun0() is going to call a function (myfun1()) so a copy of the link register (return address into main()) is saved on the stack. myfun0 calls myfun1() myfun1() follows the same rule if calling something else put lr on the stack otherwise you dont have to, myfun1() uses lr to return to myfun0(), myfun0() restores lr from the stack so it can return to main. follow that simple rule per function and you cant go wrong.
Now interrupts which not sure related or not or maybe I misunderstood your question. so arm has banked registers at least for non-cortex-m cores. but in general when an interrupt/exception occurs if the exception handler needs to use any resources/registers that are in use by the foreground task then that handler needs to preserve those on the stack in such a way that the foreground task that was interrupted had no idea this happened since interrupts in general can often occur between any two instructions, so you need to even go so far as to preserve the flags that were set by the instruction before the one you interrupted.
So apply that to arm, you have to look at which architecture you are using and see where it describes the interrupt process what registers you have to preserve and which ones you dont, which stack pointer is used, etc (something you have to setup well ahead of your first exceptions, if you are using an arm with separate interrupt stack and forground stacks).
The cortex-m is designed to do some/all of that work for you it has one stack basically and on interrupt it pushes all the registers on the stack for you so you can simply have a C compiled function just run as a handler and the hardware cleans up after you (from a preserved register perspective). Some other processors families do something like this for you, they might have a return from interrupt instruction separate from a return instruction, one is there because on interrupt the hardware saves the flags and return address but for a simple call you dont need the flags preserved.
The arm is a lot more flexible than some other instruction sets, some others you may not have any instructions that allow you to branch to an address in any register you want you may have a limitation. You might be limited on what register you use as a stack pointer or the stack pointer itself is not accessible as a general purpose register. by convention the sp is 13 in the arm, they allow the pseudo instruction of push and pop which translates into the proper ldmia r13!{blah} and stmdb r13!,{blah} but you could pick your own (if not using a compiler that follows the convention or can change an open source compiler to use a different stack pointer register). the arm doesnt prevent that. the magic of the link register r14 is nothing more than a branch link or branch link exchange automatically modifies r14, but the instruction set allows you to use basically any register to branch/return for normal function calls. The arm has just enough general purpose registers to encourage compilers to do register based parameter passing vs stack only. Some processors lean toward stack only parameter passing and have designed their return address instructions to be strictly stack based avoiding a return register all together and a rule to have to save that if nesting functions.
All of these approaches have pros and cons, in the case of arm register passing was desireable and a register based return address too, but for nesting functions you have to preserve the return address at each nesting level to not get lost. Likewise for interrupts you have to put things back they way you found them as well as be able to get back to where you interrupted the foreground.

Stack(s), Registers in ActionScript ByteCode AVM2, which all are there?

From the AVM2 Overview PDF I encountered references to two types of stacks - Scope Stack and Operand Stack.
1) I assume these are two different memory stacks, each handling different things. Are there even more stacks?
2) pushstring "hello" - this would push a start of memory address where "hello" string is located onto Operand Stack. Right?
3) setlocal 0 - this would store a value from the stack (above) into register0 by popping it off. Right?
4) PushScope() - hmm, docs say pop value of stack, push value onto Scope Stack. Why?
I know a little bit of NASM but ABC seems more complex than that. Especially I'm confused about Scope Stack and the whole concept of multiple stacks.
I am no AVM2 expert, but here's what I know:
There are only 2 stacks, the two you mention: scope and operand.
Yes, pushstring "hello" will push the string onto the operand stack.
Also, correct. setlocal0 will pop "hello" off the stack and store it in reg 0.
The scope stack is used by all operations that require a name lookup for scope, for instance closures and exceptions. Often in ASM code you'll see getlocal_0 immediately followed by a pushscope. This is pretty common. You can kind of think of it as adding the "this" object to the scope stack for future reference in method calls, scope for closures, etc.
I highly recommend downloading the Tamarin source and playing with the decompiler there. Also, Yogda looks to be pretty handy for learning: http://www.yogda.com/

What will happen if function goes out of stack space during infinite recursion?

There is a function that calls itself recursively infinitely.
This function has some arguments too.
For every function call the arguments and return address are pushed on the stack .
For each process there is fixed size of stack space that cannot grow dynamically like heap.
And I guess each thread also has its own stack.
Now if a function is called recursively infinitely and process runs out of stack space , what will happen?
Will program crash?
Will OS handle the situation?
There is 4GB of address space so why cannot OS do something to increase stack size.
stack overflow.
In UNIX and compatible the process will get terminated throwing SIGSEGV or SIGSTKFLT signal.
In Windows the process will get terminated throwing exception STATUS_STACK_OVERFLOW.
For C++ at least, you will be in the realms of "undefined behaviour" - a bit like the Twilight Zone, anything could happen.
And if the recursion is infinite, what good will increasing the stack size do? Better to fail early than later.
Depending on the language you will either get an exception (e.g. in Java) or the program will crash (in C, C++).
Typically the stack is relatively small, because that suffices, and a stack overflow signals an error. In Java you can increase the stack space with a command line option if you must.
Also note that functional languages typically compile tail recursion into a loop, and no stack space is used in that case.
This isn't language-agnostic - it very much depends on the language/platform.
In C# (or any .NET language) you'll get a StackOverflowException, which as of .NET 2.0 cannot be caught and will bring down the process.
In Java (or any JVM language) you'll get a StackOverflowError (as specified here).
I'll leave it to other answers to deal with other languages and platforms :)
A typical Unix result will be a segmentation fault. Don't know about Windows.
Yes, your program will crash. There is no way for the OS to "handle the situation", other than preventing your buggy code from damaging other processes (which it is already doing). The OS has no way of knowing what it was you really wanted your program to do, rather than what you told it to do.
There are plenty of answers what will happen, but I want to mention the extremely easy solution:
Just by a turing machine and let your code run on that. It will have plenty of space.
The program will crash. Usually stack is limited by operating systems in order to trap bugs like this before they consume ALL available memory. On Linux at least the stack size can be changed by the user by issuing the limit command in shell.