In the following code, what happens to the memory myArray initially pointed to once it's reassigned in the 2nd line? Is that memory lost, or does the C# garbage collector take care of it?
static void Main(string[] args)
{
double[] myArray = new Double[10];
myArray = new Double[3];
}
As far as I've been reading, there's no way to explicitly free up the memory, so I'm hoping C# automatically does it.
Of course, C# automatically releases memory that was associated with myArray prior to the assignment. This does not happen right away, but as soon as garbage collector realizes there are no remaining references to that Double[10] array object*, the memory allocated to the object gets reclaimed.
If you change your program slightly to create a second reference to the same array, like this
double[] myArray = new Double[10];
double[] myArray2 = myArray; // Second reference
myArray = new Double[3];
garbage collector would not release the object, as long as a reference to it remains accessible to your program.
* Sometimes your program finishes execution before garbage collector gets to complete its analysis. The memory still gets released, though.
When your variable goes out of scope and the memory is no longer required then it becomes eligible for garbage collection.
MS explains all, as seen here: https://msdn.microsoft.com/en-us/library/aa691138(v=vs.71).aspx
C# employs automatic memory management, which frees developers from manually allocating and freeing the memory occupied by objects.
Automatic memory management policies are implemented by a garbage
collector. The memory management life cycle of an object is as
follows:
When the object is created, memory is allocated for it, the constructor is run, and the object is considered live.
If the object, or any part of it, cannot be accessed by any possible continuation of execution, other than the running of
destructors, the object is considered no longer in use, and it becomes
eligible for destruction. The C# compiler and the garbage collector
may choose to analyze code to determine which references to an object
may be used in the future. For instance, if a local variable that is
in scope is the only existing reference to an object, but that local
variable is never referred to in any possible continuation of
execution from the current execution point in the procedure, the
garbage collector may (but is not required to) treat the object as no
longer in use.
Once the object is eligible for destruction, at some unspecified later time the destructor (Section 10.12) (if any) for the
object is run. Unless overridden by explicit calls, the destructor for
the object is run once only.
Once the destructor for an object is run, if that object, or any part of it, cannot be accessed by any possible continuation of
execution, including the running of destructors, the object is
considered inaccessible and the object becomes eligible for
collection.
Finally, at some time after the object becomes eligible for collection, the garbage collector frees the memory associated with
that object.
If you want to go into more detail then you can look here: https://learn.microsoft.com/en-us/dotnet/standard/garbage-collection/index
or I'm sure you can also find some blogs on the topic.
Related
I have the following function:
HashSet<string> Func()
{
HashSet<string> output = new HashSet<string>();
output.Add("string_1");
output.Add("string_2");
return output;
}
Then I call this method and copy it to a reference type:
HashSet<string> bindingObjct = Func();
This is reference copying from the return of the function "output" and the binding variable at call "bindingObjct", so both are referring to the same objects.
My question:
When garbage collector is made on "output" (the local variable inside the function), will this affects "bindingObject"? even while using "bindingObject" recently?
Garbage collection is performed on objects, not on variables. output is not garbage collected; the HashSet you created (which had a reference temporarily stored in output) will be garbage collected at some point after no live variables store references to it.
In short, the variables you're referring to will not be changed in any way. The HashSet remains valid for its lifetime. Once it's eligible for garbage collection you will no longer be able to access it (by definition; if you were able to access it, it wouldn't be eligible for garbage collection).
The GC will only collect objects that are no longer referenced anywhere - it's fairly pessimistic by default. If you have several references to the same object the .NET GC will handle this, but tracking the life of the object and graph can become a factor in performance.
So by my understanding the answer to your question is 'No', the GC will not act on an object that is referenced elsewhere
I wonder what are the situations of the GC to free the memory of a pointer.
For example:
public class Test
{
public List<int> list1;
public void test()
{
List<int> list2 = new list<int>();
list2.Add(1);
list2.Add(1);
list1 = list2;
}
}
The GC was suppose to free the memory of list2, does it because another element share the same address of list2? After the run of test()
What are the situations which the G will free the memory of an element.
In your example you create list2 as a local variable, but then you retain the reference to the underlying object in list1 before the method exits, which means the object you created in test() won't be collected (until list1 gets out of scope or changes the reference). Your object is ready to be collected only when there are no strong references to it (read about weak references if you want to know more on this subject).
Even when the object is ready to be collected, garbage collector will only run when:
There is low physical memory (OS will tell your app when there is memory pressure)
Memory used by allocated objects surpasses a certain threshold which is adjusted dynamically
New allocation cannot be made because not enough memory available
GC.Collect() was called explicitly
..
list1 retains a reference to the list after test() completes and will retain that reference for the lifetime of the instance of Test. The GC will not free up that list therefore until sometime after there is no longer any reference to Test.
When that "sometime after" occurs can be viewed as non-deterministic. It'll do it as and when it wants to. It almost certainly won't do it straight away.
does it because another element caught the address if list2?
No, it because list2 is no longer available out of scope of test(..) method.
Worth mantioning, that the pointer becomes invalid, but the memory it refers to is still "alive". Because there is another list1 that refers to the same memory
list1 = list2;
and list1 is a global var, so is not subject for destruction in this concrete case.
And more: it's not a must that GC actually frees a memory. Correct to say that the memory is marked to be garbage collected, but will be it actually cleaned or not is subject of other validations.
Your terminology is a bit mixed so I'll try to correct that.
Firstly, the GC runs automatically and asynchronously. It is also 'smart'. It will only run when required, to minimize the number of collection attempts. You should never have to interact with it.
The GC was suppose to free the memory of list2, does it because
another element caught the address if list2? After the run of test()
list1 is a class member. list2 is a local variable. list1 is always null - there is nothing to collect. A reference (no pointers in c#!) to list2 is created when you assign it to list1. list2 will now only be created when the class Test is collected.
.NET GC is a tracing, generational, mark-and-sweep collector.
It will never collect objects which are reachable, where reachable objects are ones:
which are referenced from anywhere in the call stack (that is, all local variables and parameters in the functions currently being invoked), and any global variables. These objects are called roots.
which are referenced by other reachable objects.
In your case, the new List<int>() statement creates a new list instance in memory, which is initially referenced by list2. If you didn't assign it to list1, it would have been eligible for collection as soon as list2 went out of scope (and then collected some time in the future).
Since you made your list1 field reference that same instance, after leaving the test1 method you are still left with a strong reference to that (one and only) object instance.
I'm not sure if I understand your question correctly, but the GC will remove the content of list2 because it is kept alive for only a short amount of time, due to it living on the stack and not the heap.
So, if you're wondering if the GC clears it because you've assigned list1=list2, then no. List2 would be kept alive as well but it gets killed off due to the method ending. :)
Here is a small blogpost that goes a bit more in-depth on the GC: http://it-ca.net/blogdylan/?p=354
Lets say I have something like:
public class Item
{
public string Code;
public List<string> Codes = new List<string>();
}
private void SomeMethod()
{
List<Item> Items = new List<Item>();
for (int i = 0; i < 10; i++)
{
Item NewItem = new Item();
NewItem.Code = "Something " + i.ToString();
NewItem.Codes.Add("Something " + i.ToString());
Items.Add(Item);
}
//Do something with Items
}
I am instantiating Item and not free'ing it because I need to have access to it in the list later on (rough example).
What I am wondering is when SomeMethod() has finished executing, will Items (and the contents of it - including the List<>) be de-referenced and allow the garbage collector to clean up the memory as and when it runs? Basically, will this section of code cause any memory leaks or should everything be de-referenced when SomeMethod() has finished processing.
My understanding is that when nothing holds a reference to an object it will be garbage collected so in my mind this code should be Ok but I just wanted to make sure I understand correctly.
EDIT:
If I was to add one of the objects Items is holding into another list that would still be in scope (a global list for example). What would happen?
Once your variable Items goes out of scope, the garbage collector will indeed dispose of it (and its contents, as your code is written) at its leisure.
The garbage collector will collect anything that is no longer reachable by code. Since you will no longer be able to reach your Items list or any of the Items contained within the list, then the garbage collector will collect them at some point. Your understanding of the garbage collector is correct.
Ok,
List<Item> Items
is declared in the scope of the method. So when the method ends, it goes out of scope and is the list is dereferenced.
The memory will be released at some point after that, when the Garbage Collecter sees fit.
As an aside, since Items is declared in a "local" scope I'd prefer to call it items.
all the variables in the method are in a stackframe and all these variable will be destoried along with the stackframe after the method was executed.
that is said after SomeMethod() executed, the variable Items will nolonger exists, thus new List() will be marked "can be collected".
the second question is that, there is a globle list variable hold the reference of one of the object that in the variable Items, then after the SomeMethod() executed, the List in the SomeMethod will be marked as "can be collected", and all the other object beside the item that was referenced by the globle list variable will also be makred as "can be collected"
the reason is, the list actually hold the reference that point to the exact object in the heap
So the shared object can not be collected due to the reason that it is referenced by the globleList
In order to keep things sane and keep its job, GC has to promise two things:
Garbage will be collected. This seems pretty obvious, but if the GC doesn't promise to clean up managed objects without you having to tell it to, it's rather useless.
ONLY garbage will be collected. You don't have to worry about the GC cleaning up objects that are still in play.
So, once Items goes out of scope (that is, once the function returns), it's no longer reachable by running code, so it's eligible for collection without you having to do anything. Since the items in the list are no longer reachable either (their only link was in the list), they're eligible too. If you returned a reference to an entry in the list, though, that object is still in play and can't be collected yet. GC will do the right thing.
In fact, GC almost always does the right thing. There are really only three major cases you have to worry about:
If you're buiding a container (like if you're making your own List workalike). Any objects that no longer "exist" in the container as far as the user is concerned, should generally be set to null so the GC doesn't see them as reachable through your collection and erroneously keep them alive. If you remove an item from the collection, for example, null out the reference or overwrite it with another.
With large (>~85KB?) objects. They'll typically stick around in memory til they crowd out everything else, at which point a full GC cycle runs. (Normally, only certain likely-to-be-discarded objects are checked during a cycle. Full collections check pretty much everything, which takes significantly longer but might free more memory.)
If you're using IDisposable objects or native/unmanaged resources. Some incompetents don't know how to implement IDisposable correctly. If you're dealing with a library created by such an incompetent, then you'll need to ensure that you Dispose stuff, or only ever use it within a using block, or things can get really weird. (If you only use the .net API, you're pretty safe. But disposing is still good manners.)
For pretty much all other occasions, GC just works. Trust it.
private button btnNew=new button();
btnNew.addclickhandler(this);
private DataGrid grid;
private void onClick(event click) {grid=new DataGrid();}
Hello ,I write a code like this sample ,I want to know that every time a user click on btnNew,what is going on in heap and stack memory?for example does a new block in heap memory assign to this grid?Or an older block remove and this new block replace it ?Or an older block remains in heap memory and also new block assign to it.
Is this block of code allocate a huge memory on several click?
**The DataGrid could be replace with any component I want to know about this type of new statement usage and memory allocation **
sorry, for my bad english!
.
what is going on with respect to heap
and stack memory?
since the button is reference type and declared in global will be allocated in heap, not in stack.
Is a new block in heap memory assigned to this button?
yes if memory is available, else unreached references will be removed and this one is allocated
Does this block of code allocate a
large amount of memory on a single
click?
No, but it will, if you add thousand buttons
Check out this cool article Memory in .NET - what goes where by Jon Skeet to understand the memory internals better..
Cheers
This is a huge topic. This is akin to asking "you type www.amazon.com into a browser. What happens next?" To answer that question fully you have to explain the architecture of the entire internet. To answer your question fully you have to understand the entire memory model of a modern operating system.
You should start by reading about the fundamentals of memory and garbage collection, here:
http://msdn.microsoft.com/en-us/library/ee787088.aspx
and then ask more specific questions about things you don't understand.
Using the new statement allocates memory on the heap. In general new memory is allocated. If the btnNew pointer was the only pointer associated with a button object, it should become a target to the garbage collector. So the memory will be freed again. For multiple clicks the same will happen, but you should be aware that the garbage collector does not work in real time. So in a high-frequency loop allocating large objects - "new" can become a problem in c#.
if button is a class (ref type), it is allocated on the heap. (value-types are allocated on the stack in the current CLR implementation, unless they are contained by another reference type or captured in a closure - in which case they are on the heap.).
The garbage collector has pre-allocated segments of memory of different sizes corresponding to generations 0, 1 and 2. WHen you new up an object, it is allocated in generation 0. And this allocation is really fast, since it is just moving a pointer by a delta = size of the object. The CLR clears the values in the object to default values as a prereq step before executing the ctor.
Periodically all threads are paused and the garbage collector runs. It creates a graph of reachable objects by traversing "roots". All unreachable objects are discarded. The generation segments are moved around / compacted to avoid fragmentation. Gen 0 is collected more frequently than 1 and so on... (since Gen-0 objects are likely to be short-lived objects). After the collection, the app threads resume.
For more on this, refer to documents explaining the garbage collector and generations. Here's one.
I am a bit confused about the fact that in C# only the reference types get garbage collected.
That means GC picks only the reference types for memory de-allocation.
So what happens with the value types as they also occupy memory on stack ?
For a start, whether they're on the stack or part of the heap depends on what context they're part of - if they're within a reference type, they'll be on the heap anyway. (You should consider how much you really care about the stack/heap divide anyway - as Eric Lippert has written, it's largely an implementation detail.)
However, basically value type memory is reclaimed when the context is reclaimed - so when the stack is popped by you returning from a method, that "reclaims" the whole stack frame. Likewise if the value type value is actually part of an object, then the memory is reclaimed when that object is garbage collected.
The short answer is that you don't have to worry about it :) (This assumes you don't have anything other than the memory to worry about, of course - if you've got structs with references to native handles that need releasing, that's a somewhat different scenario.)
I am a bit confused about the fact that in C# only the reference types get garbage collected.
This is not a fact. Or, rather, the truth or falsity of this statement depends on what you mean by "get garbage collected". The garbage collector certainly looks at value types when collecting; those value types might be alive and holding on to a reference type:
struct S { public string str; }
...
S s = default(S); // local variable of value type
s.str = M();
when the garbage collector runs it certainly looks at s, because it needs to determine that s.str is still alive.
My suggestion: clarify precisely what you mean by the verb "gets garbage collected".
GC picks only the reference types for memory de-allocation.
Again, this is not a fact. Suppose you have an instance of
class C { int x; }
the memory for the integer will be on the garbage-collected heap, and therefore reclaimed by the garbage collector when the instance of C becomes unrooted.
Why do you believe the falsehood that only the memory of reference types is deallocated by the garbage collector? The correct statement is that memory that was allocated by the garbage collector is deallocated by the garbage collector, which I think makes perfect sense. The GC allocated it so it is responsible for cleaning it up.
So what happens with the value types as they also occupy memory on stack ?
Nothing at all happens to them. Nothing needs to happen to them. The stack is a million bytes. The size of the stack is determined when the thread starts up; it starts at a million bytes and it stays a million bytes throughout the entire execution of the thread. Memory on the stack is neither created nor destroyed; only its contents are changed.
There are too many verbs used in this question, like destroyed, reclaimed, deallocated, removed. That doesn't correspond well with what actually happens. A local variable simply ceases to be, Norwegian parrot style.
A method has a single point of entry, first thing that happens is that the CPU stack pointer is adjusted. Creating a "stack frame", storage space for the local variables. The CLR guarantees that this space is initialized to 0, not otherwise a feature you use strongly in C# because of the definite assignment rule.
A method has a single point of exit, even if you method code is peppered with multiple return statements. At that point, the stack pointer is simply restored to its original value. In effect it "forgets" that the local variables where ever there. Their values are not 'scrubbed' in any way, the bytes are still there. But they won't last long, the next call in your program are going to overwrite them again. The CLR zero-initialization rule ensures that you can never observe those old values, that would be insecure.
Very, very fast, takes no more than a single processor cycle. A visible side-effect of this behavior in the C# language is that value types cannot have a finalizer. Ensuring no extra work has to be done.
A value type on the stack is removed from the stack when it goes out of scope.
Value types are destroyed as soon as they go out of scope.
value types would get deallocated when the stack frame is removed after it has been executed i would assume
Would also like to add that stack is at a thread level, and heap is at application domain level.
So, when a thread ends it would reclam the stack memory used by that specific thread.
Every value type instance in .NET will be part of something else, which could be a larger enclosing value type instance, a heap object, or a stack frame. Whenever any of those things come into being, any structures within them will also come into being; those structures will then continue to exist as long as the thing containing them does. When the thing that contains the structure ceases to exist, the structure will as well. There is no way to destroy a structure without destroying the container, and there is no way to destroy something that contains one or more structures without destroying the structures contained therein.