Is there a difference between data structure stack and hardware stack? - data-structures

I've debated with my friend about the difference between data structure stack and hardware stack(call stack). I thought they are perfectly same because they both have 'push' and 'pop' that can deal with only the latest element. But my friend said that they're not same at all, but they share only the same name, 'stack'. And he thinks so because in call stack, we can access addresses that are not the latest ones, contradicting the definition of stack(data structure). Can you give an answer to this?

Here are some differences:
Usually you can only have one hardware stack (per thread).
You can have as many software stacks as desired.
Usually hardware stack is managed by the CPU directly.
Software stack access is managed explicitly from the code.
Hardware stack is usually directly related to call stack (caller functions, their arguments).
Software stack is independent of the hardware call stack (you can push item in a function and pop them in another one independently of hardware stack level).
Hardware stack memory is managed bu the OS or CPU (might be limited).
Software stack memory is managed by the application.
Well basically both stack have push and pop operations and thus work like a stack.
It would be possible to have pure or not pure hardware or software stack. Usually, hardware stack would be able to access items at a relative position from the top for arguments. On software stack, usually the protection would essentially be a private access.
On some embedded device, the stack might serve only for returns addresses and a software based stack might be needed for arguments. On some device, the maximum level can be very low.

The first is a data structure and the second is a data structure applied.
Like most applications of data structures in the real world it's not pure and has features added for convenience or speed.

Related

Are stack and heap memory actually implemented as stack and heap data structures?

I would like to know whether the stack and heap referred to in stack and heap memory are actually implemented as stack and heap data structures?
I think the stack is actually a stack that has pointers to the LIFO (Last In First Out) variables declared in functions however I wanted to confirm and also ask whether the heap shares more than just its name to the dynamic tree data structure that satisfies the heap property? I have read a lot recently on the stack and heap and believe I understand the concept however it then made me curious about the actual implementation. I imagine it could be different on different architectures too and there may not be a specific general answer for all computers and OS's.
In case anyone comes upon this question who is still unsure of what and where are the stack and heap please see this question and other links I found useful in learning the stack and heap concept.
What and where are the stack and heap?
http://gribblelab.org/CBootcamp/7_Memory_Stack_vs_Heap.html
http://www.programmerinterview.com/index.php/data-structures/difference-between-stack-and-heap/
https://www.youtube.com/watch?v=_8-ht2AKyH4
The memory heap is decidedly not a heap data structure. That is, it's not a priority queue. I suppose you could use a priority queue heap to build a memory heap, but there are much better ways to do it.
The stack is ... well ... Typically, the stack is a fixed block of memory allocated to the process. The processor itself treats that block of memory like a pure stack. That is, the processor's stack pointer points to the top of stack, and the push and pop instructions work as expected, adding things to and removing things from the stack. In that way, it's LIFO.
However, the processor can do all manner of things with the stack: push and pop different sized things, address directly into it (i.e. view the third item without popping the first two), etc. So although the processor stack does have push and pop instructions, it also has much more extended functionality. I wouldn't call it a pure LIFO data structure.
Heap memory : It doesn`t have to be a heap data structure. A heap serves as a non-fixed size memory area on virtual memory and the functionalities it exposes to programmers are allocations and frees. A heap can be implemented with various data structures . Regarding native C and C++ development , the heap memory structure will be defined by the allocators you are using. They will be responsible for managing the necessary data structures and the virtual memory. In the link below, you can see the default implementations on Windows, Linux and MacOS : http://core-analyzer.sourceforge.net/index_files/Page335.html
Stack memory: It doesn`t have to be implemented as a stack ( first in last out ) data structure , however the functionality it exposes ( not to programmers) is in form of a stack data structure. ( Processor will treat that memory given by operating system as a stack data structure ) It is a fixed size memory area on virtual memory. In modern operating systems, stacks will be per thread , and you can also define that limit by using ulimit in Linux , on the other hand in Windows side it is a linker parameter : https://msdn.microsoft.com/en-US/library/8cxs58a6(v=vs.120).aspx
Here is also another nice reading : http://duartes.org/gustavo/blog/post/anatomy-of-a-program-in-memory/

Some clarification on TCB of an operting system

I'm a computer undergraduate taking operating systems course. For my assignment, I am required to implement a simple thread management system.
I'm in the process of creating a struct for a TCB. According to my lecture notes, what I could have in my TCB are:
registers,
program counter,
stack pointer,
thread ID and
process ID
Now according to my lecture notes, each thread should have its own stack. And my problem is this:
Just by storing the stack pointer, can I keep a unique stack per thread? If I did so, won't one stack of a thread over write other's stack?
How can I prevent that? Limit the stack for each thread??? Please tell me how this is usually done in a normal operating system.
Please help. Thanks in advance.
The OS may control stack growth by monitoring page faults from inaccessible pages located around the stack portion of the address space. This can help with detection of stack overflows by small amounts.
But if you move the stack pointer way outside the stack region of the address space and use it to access memory, you may step into the global variables or into the heap or the code or another thread's stack and corrupt whatever's there.
Threads run in the same address space for a reason, to share code and data between one another with minimal overhead and their stacks usually aren't excepted from sharing, from being accessible.
The OS is generally unable to do anything about preventing programs from stack overflows and corruptions and helping them to recover from those. The OS simply doesn't and can't know how an arbitrary program works and what it's supposed to do, hence it can't know when things start going wrong and what to do about them. The only thing the OS can do is just terminate a program that's doing something very wrong like trying to access inaccessible resources (memory, system registers, etc) or execute invalid or inaccessible instructions.

Does coroutine stacks grow in Lua, Python, Ruby or any other languages?

There are some languages which support deterministic lightweight concurrency - coroutine.
Lua - coroutine
Stack-less Python - tasklet
Ruby - fiber
should be many more... but currently I don't have much idea.
Anyway as far as I know, it needs many of separated stacks, so I want to know how these languages handle the stack growth. This because I read some mention about Ruby Fiber which comes with 4KB - obviously big overhead - and they are advertising this as a feature that prevents stack overflow. But I don't understand why they're just saying the stacks will grow automatically. It doesn't make sense the VM - which is not restricted to C stack - can't handle stack growth, but I can't confirm this because I don't know about internals well.
How do they handle stack growth on these kind of micro-threads? Is there any explicit/implicit limitations? Or just will be handled clearly and automatically?
For ruby:
As per this google tech talk the ruby vm uses a slightly hacky system involving having a copy of the C stack for each thread and then copying that stack on to the main stack every time it switches between fibers. This means that Ruby is still restricts each fibre from having more than a 4KB stack but the interpreter does not overflow if you switch between deeply nested fibres.
For python:
task-lets are only available in the stackless variant. Each thread gets its own heap based stack as the stackless python vm uses heap based stacks. This mess they are inherently only limited to the size of the heap in stack growth. This means that for 32 bit systems there is still an effective limit of 1-4 GB.
For Lua:
Lua uses a heap based stack so are inherently only limited to the size of the heap in stack growth. Each coroutine gets its own stack in the memory. This means that for 32 bit systems there is still an effective limit of 1-4 GB.
To add a couple more to your list C# and VB.Net both now support async/await. This is a system that allows the program to preform a time consuming operation and have the rest of that function continue afterwards. This is implemented by creating an object to represent the method with a single method that is called to advance to the next step in the method which is called when you attempt to get a result and various other internal locations. The original method is replaced with one that creates the object. This means that the recursion depth is not affected as the method is never more than a few steps further down the stack than you would expect.

Call stack management is machine dependent?

I think I understand the basic of stack memory, but I still do not fully understand which is responsible for the mechanism for the way managing the stack - is it the compiler, the cpu architecture? is it programming language dependent?
For example, I read that in ARM there is tendency to reduce the use of stack in function calls, so arguments to functions are usually passed through 4 registers. However, it seems to me that this can be implemented using general purpose registers in other cpu's as well. How can the architecture impose this demand?
Elsewhere I read that in FORTRAN 77 there is no use of the stack.
And there is the question of the stack growing upwards/downwards. who is responsible for it?
Overall I wish to know is it cpu dependent and how is it imposed? otherwise which is responsible for these decisions?
Thanks.
It can't be imposed by the processor. Calling conventions are determined by the compiler, and most compilers will not break their language standard just to do this.
The growth direction of the stack is determined by the processor as long as the process uses things like push/pop. If they access esp directly, they should follow, but don't have too.

How many stacks does a windows program use?

Are return address and data mixed/stored in the same stack, or in 2 different stacks, which is the case?
They are mixed. However, it depends on the actual programming language / compiler. I can image a compiler allocating space for local variable on the heap and keeping a pointer to the storage on the stack.
There is one stack per thread in each process. Hence, for example, a process with 20 threads has 20 independent stacks.
As others have already pointed out, it's mostly a single, mixed stack. I'll just add one minor detail: reasonably recent processors also have a small cache of return addresses that's stored in the processor itself, and this stores only return addresses, not other data. It's mostly invisible outside of faster execution though...
It depends on the compiler, but the x86 architecture is geared towards a single stack, due to the way push and pop instructions work with a single stack pointer. The compiler would have to do more work maintaining more than one stack.
On more note: every thread in Win32 has its own stack. So, when you tell "windows program" - it depends on how many threads it has. (Of course threads are created/exited during the runtime).

Resources