I am learning GC on .net. I would like to know, where are my integers, floats or value types, static variable stored, Member of the functions, value types in the function are stored.
Any documents or any weblink you have on this topics, please post it here.
Thank you,
Harsha
I have an article which talks about this a bit, but you should really read various blog posts by Eric Lippert. "The truth about value types" is probably the most important one, along with "The stack is an implementation detail" (part one; part two).
Fundamentally it's more important to understand garbage collection in terms of reachability etc, rather than the implementation details of what goes where in memory. That can be helpful in terms of performance, but you need to keep reminding yourself that it's an implementation detail.
Note: Jon Skeet's Answer is more Correct
Stack memory:
The stack is the section of memory that is allocated for automatic variables within functions.
Data is stored in stack using the Last In First Out (LIFO) method. This means that storage in the memory is allocated and deallocated at only one end of the memory called the top of the stack. Stack is a section of memory and its associated registers that is used for temporary storage of information in which the most recently stored item is the first to be retrieved.
Heap memory
On the other hand, heap is an area of memory used for dynamic memory allocation. Blocks of memory are allocated and freed in this case in an arbitrary order. The pattern of allocation and size of blocks is not known until run time. Heap is usually being used by a program for many different purposes.
The stack is much faster than the heap but also smaller and more expensive.
Example: (Its for C though not C#)
int x; /* static stack storage /
main() {
int y; / dynamic stack storage /
char str; / dynamic stack storage /
str = malloc(50); / allocates 50 bytes of dynamic heap storage /
size = calcSize(10); / dynamic heap storage */
Above content Taken from Here
Related
I believe that following two pieces of code should be equivalent:
// first example
string s = "Hello memmory";
ReadOnlyMemory<char> memory = s.AsMemory();
using (MemoryHandle pin = memory.Pin())
{
Span<char> span = new Span<char>(pin.Pointer, 1);
Console.WriteLine(span[0]);
}
// second example
ReadOnlySpan<char> span2 = memory.Span;
Console.WriteLine(span2[0]);
Both codes will print "H".
What I don't understand is where is the unpinning of memory in the second example.
As I understand it string is allocated on Heap, MemoryHandle pinn it and create Span from the pointer. MemoryHandle.Dispose unpin memory back.
I believe that memory.Span must pin the memory as well, otherwise span couldn't accessing the pointer. But how is the memory unpinned in the second example?
The last assumption is incorrect: memory.Span does not need to pin the memory, as the garbage collector is aware of its underlying reference. Pinning is independently available in case you would like to pass the pointer to a native API.
A Span only lives on the stack of the current method thread and not on the Heap of it therefore will it be alive as long as you using it there. So far so clear.
Now the funny part:
The clear truth is that the result of memory.Span is not pinned but only referenced by using the ref T inside the Span<T> what is .nets idea of managed pointers that are also observed by the GarbageCollector.
As long as your Memory lives, your span will too and by this your Span.
References:
https://msdn.microsoft.com/en-us/magazine/mt814808.aspx?f=255&MSPPError=-2147217396
https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/ref#ref-struct-types
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.
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.
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.
I found a blog entry which suggests that sometimes c# compiler may decide to put array on the stack instead of the heap:
Improving Performance Through Stack Allocation (.NET Memory Management: Part 2)
This guy claims that:
The compiler will also sometimes decide to put things on the stack on its own. I did an experiment with TestStruct2 in which I allocated it both an unsafe and normal context. In the unsafe context the array was put on the heap, but in the normal context when I looked into memory the array had actually been allocated on the stack.
Can someone confirm that?
I was trying to repeat his example, but everytime I tried array was allocated on the heap.
If c# compiler can do such trick without using 'unsafe' keyword I'm specially intrested in it. I have a code that is working on many small byte arrays (8-10 bytes long) and so using heap for each new byte[...] is a waste of time and memory (especially that each object on heap has 8 bytes overhead needed for garbage collector).
EDIT: I just want to describe why it's important to me:
I'm writing library that is communicating with Gemalto.NET smart card which can have .net code working in it. When I call a method that returns something, smart card return 8 bytes that describes me the exact Type of return value. This 8 bytes are calculated by using md5 hash and some byte arrays concatenations.
Problem is that when I have an array that is not known to me I must scan all types in all assemblies loaded in application and for each I must calculate those 8 bytes until I find the same array.
I don't know other way to find the type, so I'm trying to speed it up as much as possible.
Author of the linked-to article here.
It seems impossible to force stack allocation outside of an unsafe context. This is likely the case to prevent some classes of stack overflow condition.
Instead, I recommend using a memory recycler class which would allocate byte arrays as needed but also allow you to "turn them in" afterward for reuse. It's as simple as keeping a stack of unused byte arrays and, when the list is empty, allocating new ones.
Stack<Byte[]> _byteStack = new Stack<Byte[]>();
Byte[] AllocateArray()
{
Byte[] outArray;
if (_byteStack.Count > 0)
outArray = _byteStack.Pop();
else
outArray = new Byte[8];
return outArray;
}
void RecycleArray(Byte[] inArray)
{
_byteStack.Push(inArray);
}
If you are trying to match a hash with a type it seems the best idea would be to use a Dictionary for fast lookups. In this case you could load all relevant types at startup, if this causes program startup to become too slow you might want to consider caching them the first time each type is used.
From your line:
I have a code that is working on many small byte arrays (8-10 bytes long)
Personally, I'd be more interested in allocating a spare buffer somewhere that different parts of your code can re-use (while processing the same block). Then you don't have any creation/GC to worry about. In most cases (where the buffer is used for very discreet operations) with a scratch-buffer, you can even always assume that it is "all yours" - i.e. every method that needs it can assume that they can start writing at zero.
I use this single-buffer approach in some binary serialization code (while encoding data); it is a big boost to performance. In my case, I pass a "context" object between the layers of serialization (that encapsulates the scratch-buffer, the output-stream (with some additional local buffering), and a few other oddities).
System.Array (the class representing an array) is a reference type and lives on the heap. You can only have an array on the stack if you use unsafe code.
I can't see where it says otherwise in the article that you refer to. If you want to have a stack allocated array, you can do something like this:
decimal* stackAllocatedDecimals = stackalloc decimal[4];
Personally I wouldn't bother- how much performance do you think you will gain by this approach?
This CodeProject article might be useful to you though.