how variables are stored on stack? - c#

I've read that there are two regions of memory one stack and other heap. Basic data types like int, double, float etc. are stored on stack while reference types are stored on heap. As we know that stack is LIFO that means last element pushed will be removed first. now assuming following code
int first = 10;
double second = 20.0;
float third = 3.0F;
so, first will be pushed first, then second and then third. so variable third which is of type float will be on top of the stack but if I use following code (assuming in C#)
Console.WriteLine(second);
how value of variable second will be accessed while variable third is on top of the stack?

You misunderstand what the stack is actually referring to. There is a data structure Stack which uses push and pop to store data, but stack based and head based memory are a far more abstract concept. You might try looking at the Wiki article on stack based memory allocation, but you will need to know more about assembly and frame pointers as well. There are entire classes taught on this subject.

Stack behaves as LIFO with PUSH and POP insturctions.But that doesnt mean without pop you can read the stack memory .
In your case
you
push int first (* its not a opcode of machine, just trying to explain)
push double second
push float third
Now you have 2 options to access the variables that you have pushed.
1) pop -> This is the one that reads and makes stack look like lifo.
if you pop it
stack will be
int first
double second.
Bsically it removes(not exactly,just a register is chaged to show the stacks last valid memory position)
2) But if you want you can jst read it without pop.Thus not removing the last times.
So you will say Read me double.And it will access the same way it does in heaps..
That will cause machine to execute a mov instruction .
Please note its EBP(Base pointer) and ESP(Stack pointer) that points to the location of a stacks variables.And machines read variables as mov eax,[ebp+2(distance of "second" from where base pointer is now pointing]].

I think you have misunderstood the concept.
Eric Lippert's has a several posts on the topic that I would recommend reading. Memory management is an advanced topic.
The Stack Is An Implementation Detail, Part One
The Stack Is An Implementation Detail, Part Two
The Truth About Value Types
Also, found this great answer on what lives on the stack from Marc Gravell, copied below.
"All VALUE Types will get allocated to Stack" is very, very wrong;
struct variables can live on the stack, as method variables. However,
fields on a type live with that type. If a field's declaring type is a
class, the values are on the heap as part of that object. If a field's
declaring type is a struct, the fields are part of that struct
where-ever that struct lives.
Even method variables can be on the heap, if they are captured
(lambda/anon-method), or part of (for example) an iterator block.

Related

when is memory allocated for value types in c#?

static void Main()
{
int i;
int j;
j=10;
i=2;
}
Is the memory allocated in stack for variables in the order in which their declaration appears or will it be allocated as they are initialized?
I think variables are loaded onto stack in the order in which they are declared while peers argue otherwise. So, according to them j is pushed onto stack first while i argue that i is pushed to stack first. who is correct?
The short answer is that you can not know the exact order of stack allocations.
Operations may be reordered by both the compiler and the processor for optimization purposes. And as Ehsan already pointed out in a comment, your code might not even be executed at all when a release build is used.
Have a look at this article The C# Memory Model, it may help explain why the exact order of allocation is not really something you can know beforehand.

Does the value type variable violates the LIFO nature of stack

I have assigning a value to value type say for an example
int i=0;
int j=1;
Since int is a value type variable the memory is allocated in the Stack as follows(push the value of I and j to stack):
|_|<-- stack top
|1|<--j value
|0|<--i value
I have few doubts regarding this allocation :
If i execute i+=1 in this time what will be the changes in the stack allocation?
How it is possible to pop the value of i without poping j
if i re assign the of i then the value will be stored in the stack top, in this time what happens to the previously assigned value:
Your mental model is badly broken, you take the word "stack" too literally. The processor stack behaves like a stack only when one method calls another. Within a method, the arguments and local variables are stored in a stack frame. It is freely addressable, no pushes or pops. Always as offsets from either the base pointer register or stack pointer register. EBP in 32-bit code, RSP in 64-bit code. The size of the stack frame depends on the number of local variables. It is "allocated" simply by decrementing the stack pointer by the frame size. And "destroyed" simply by restoring the stack pointer.
You'd be closer if you model it as a C# Stack<object[]> data structure.
The Wikipedia article should help to clarify the concept.
Local variables are not pushed and popped when you create and read them.
In the start of the method is code to create a stack frame to make room for local variables. This is done by moving the stack pointer to create a memory area on the stack that the method can use.
Each local variable has a fixed position in the stack frame from the start, even if the scope of a variable is smaller than the method. The stack frame doesn't change during the execution of the method.
| |
| More stack data |
| |
+------------------------+
| Method return address |
+------------------------+
| i | Stack frame
| j |
+------------------------+
<--- stack pointer
Typically the bp register is set to point to the stack frame, so [bp + 0] accesses i and [bp + 4] accesses j.
At the end of the method there is code to remove the stack frame by putting the stack pointer back, so that the return address is next to be popped.
(Note that this is an implementation detail, and the JIT compiler might for example use a register to store a variable instead of space in the stack frame, and when closures come into the picture it changes things, but it works as a starting point for understanding how local variables work.)
You need to take into consideration the following information:
C# is a just in time compiled language, and the .NET CLR is responsible for producing machine code from .NET code during program execution.
Modern CPUs have a register set that are used intensively to avoid the need of going to stack for each operation.
Therefore, in your code, the .NET CLR will most likely place i and j variables into registers and most likely will arrange the code so that only when there are no more registers to use, temporary variables will be placed on the stack.
However that stack is not a plain LIFO structure. Accesses to stack variables can be made using EBP and ESP registers as base respectively offsets.

does an object created in a parameter to function get copied to both stacks?

If class x calls y by going y.create(new z) does the z obj get created in x's stack as well as y's? This is assuming we are passing by value, not ref or ptrs
A couple of things:
The stack/heap is on the process (application) level, not at an object level. The entire application shares one stack (at least in the context of your question), no matter how many objects it is using.
Unless the "z" in your example is a value type (like a struct), it won't ever fully reside on the stack. If "z" is a class, then it "lives" on the heap, with only a reference to it on the stack.
You really should read this short explanation from Jon Skeet, especially "A worked example" towards the bottom.
The object z is created in the applications allocated memory. Each function does not have its own memory area when using new to create objects.
I would suggest that you read up on the content on this page, I certainly find it useful from time to time (ie when i get things mixed up)

Stack overflow in C# application

I am new to the concept of memory division in programming. I have found that size of stack is in most cases in .NET applications 1MB round. My question is: "How doesn't the stack overflow appear when in some functions I use local variables for "Image" type that is bigger than 1MB. Thanks in advance.
Because a StackOverflow exception has nothing to do with stack or heap memory management. Per the MSDN Documentation:
The exception that is thrown when the execution stack overflows because it contains too many nested method calls. This class cannot be inherited.
Now, if you're talking about the stack as far as the memory is concerned, then we're in a different world. The images you're storing in memory are likely held on the Large Object Heap. Memory management, and the conversation of it, is much too broad for this forum - but if you have a specific question about memory management then we can address that.
It's important that you understand that you are mixing two nomenclatures, and concepts, in your question and that there is an explicit difference between the two. I don't want you to go on thinking that you should be getting a StackOverflow exception because of large objects. I also don't want you to go on thinking that you are getting a StackOverflow exception because of large objects and memory management.
The image itself is not stored on the stack, it is stored on the heap. Only a pointer/reference to the image is kept on the stack, which is a lot smaller.
public static void DoSomethingToImage()
{
Image img = new Image(...);
}
In the above code fragment, the Image is allocated on the heap and a reference to the image is stored in the img variable on the stack.
Only local variables that are value types are allocated only on the stack. For a reference type like Image only the reference is allocated on the stack, the object is allocated on the heap.
Your local variables are actually references ("pointers"). Those images are not stored on the stack ;)
The main reason for a stack overflow error to happen is to have a large count of functions calls, an example that would through this error would be like this:
static int x = 0;
static void Main()
{
fn();
}
static void fn()
{
Console.WriteLine(x++);
fn();
}
This happens due to something wrong at the code, because this usually happens after few thousands of calls.
The application above exited like this:
...
15706
15707
15708
Process is terminated due to StackOverflowException.
You could learn to see the "Call Stack" windows in the debugger, it will display the list of function calls.

Does the amount of code make a data structure larger?

I have an arraylist of items that only have maybe ten variables in them. But the items have a good bit of code, and I'd like to add more. I'm curious how this will effect the size of my structure. My intuition tells me each one has a stack, but with arguments getting passed around and stuff I've probably not considered I'm unsure. So roughly just how much is code adding to my data structure?
Code does not add to the size of your structure.
The code associated with a class is not usually duplicated per-instance so adding code should not impact the size of your arraylist.
Even though you put code in the same set of curly braces as data, the compiler will separate it out and put it in a different memory section.
That way, you only need one copy of the code - it's not necessary to make a new copy for each item that uses it.
Only in very large projects does the actual size of the compiled code become a problem; usually, it's not much bigger than the source text. On small programs, it's typically a few hundred K or a meg or two at most. It's not worth worrying about on modern machines.
The size of an object instance is (mostly) the sum of its data members. Function members are not stored per-instance, and have no effect on instance size.
Your program has a single stack per thread. When a function is called, stack memory is reserved for each parameter and variable of that function, and freed when it returns.
Your object is stored on the stack if it is instantiated in a function without new. If you use new, only a reference is stored on the stack, and the instance itself is stored on the heap.
:)
Code is not stored on the heap.
Regardless of how many objects you create, you'll only have the code in one place.
The class member functions on which object works are stored differently and it has no effect on size of the object. Where as data members inside the class will be part of the object and object size will change if you change the type of the variable.
ex:
class Test
{
1. member functions
//it does not matter how many functions you have, this section does not contribute
// to object size
2. member variables
//this contributes to the object size, define an int or double etc will change the object size
}
Each object does not have its own stack. Stacks are per thread/process, not per object.

Categories

Resources