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
Related
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.
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
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.
I have a design and I am not sure if garbage collection will occur correctly.
I have some magic apples, and some are yummy some are bad.
I have a dictionary : BasketList = Dictionary <basketID,Basket>
(list of baskets).
Each Basket object has a single Apple in it and each Basket stores a reference to an objectAppleSeperation.AppleSeperation stores 2 dictionaries, YummyApples = <basketID,Apple> and BadApples = Dictionary<basketID,Apple>, so when I'm asked where an apple is I know.
An Apple object stores BasketsImIn = Dictionary<ID,Basket>, which points to the Basket and in Shops, and the Apple in Basket.
My question is, if I delete a basket from BasketList and make sure I delete the Apple from BadApples and/or YummyApples, will garbage collection happen properly, or will there be some messy references lying around?
You are right to be thinking carefully about this; having the various references has implications not just for garbage collection, but for your application's proper functioning.
However, as long as you are careful to remove all references you have set, and you don't have any other free-standing variables holding onto the reference, the garbage collector will do its work.
The GC is actually fairly sophisticated at collecting unreferenced objects. For example, it can collect two objects that reference each other, but have no other 'living' references in the application.
See http://msdn.microsoft.com/en-us/library/ee787088.aspx for fundamentals on garbage collection.
From the above link, when garbage collection happens...
The system has low physical memory.
The memory that is used by allocated objects on the managed heap surpasses an acceptable threshold. This means that a threshold of acceptable memory usage has been exceeded on the managed heap. This threshold is continuously adjusted as the process runs.
The GC.Collect method is called. In almost all cases, you do not have to call this method, because the garbage collector runs continuously. This method is primarily used for unique situations and testing.
If you are performing the clean-up properly, then you need not worry!
I have a double linked list (queue) I have made on my own.
I am wondering, to clear the linked list, is it enough to simply remove the head and tail references?
E.g
public void Clear()
{
Head = null;
Tail = null;
}
I am imaging a domino effect, but I am having a hard time testing it.
It WILL make the whole object appear empty atleast. All data requests (such as peek, dequeue etc.) returns null.
You can also easily Enqueue some new objects.
Purely functional it seems to be working.
But I'd really like to know if I am doing it the right way.
The short answer is yes, garbage collection will clear out all the linked list nodes, provided that nothing external holds a reference to them.
Easiest way to test is to add a finalizer to your linked list node object that outputs some logging. Note that you can't be sure when the garbage collector runs (without forcing it, via GC.Collect()) so you won't see the finalizer called as soon as you call you Clear() method.
The "domino effect" is not going to happen, though; it doesn't matter if references are held to an object, rather than references can be traced back to the stack or a static object. So if several objects refer to each other, but nothing refers to them, then they'll all be garbage collected simultaneously.
Unless the objects in the collection needs to be disposed of, and it is the responsibility of the collection to do that, then your method is probably the best way.
Since there is no root to the object (no live references), garbage collection can pick it up and remove it.
I am imaging a domino effect
This isn't how the GC works.
The GC first marks everything "dead", then starting at the root objects it traverses all objects referenced by them, marking each one as "alive".
Since your list is no longer reference by any root objects (or children of) it will be left marked "dead".
The second pass then frees the "dead" objects.
I doubt that you can assume in a finalizer that any objects either side in the list have not been collected first, ie it will be in the GC's own order not the order of the list.
A bit more detail here:-
http://msdn.microsoft.com/en-us/magazine/bb985010.aspx