Quote from ( Safe in C# not in C++, simple return of pointer / reference, answer 3) by Eric lippert.
Also, note that it is not any reference to the Person object that keeps it alive. The reference has to be rooted. You could have two Person objects that reference each other but are otherwise unreachable; the fact that each has a reference does not keep them alive; one of the references has to be rooted.
I dont understand, can someone explain what a rooted reference is?
It means a GC root.
Have a read through this article, maybe it will help with your understanding:
GC roots are not objects in themselves but are instead references to objects. Any object referenced by a GC root will automatically survive the next garbage collection. There are four main kinds of root in .NET:
A local variable in a method that is currently running is considered to be a GC root. The objects referenced by these variables can always be accessed immediately by the method they are declared in, and so they must be kept around. The lifetime of these roots can depend on the way the program was built. In debug builds, a local variable lasts for as long as the method is on the stack. In release builds, the JIT is able to look at the program structure to work out the last point within the execution that a variable can be used by the method and will discard it when it is no longer required. This strategy isn’t always used and can be turned off, for example, by running the program in a debugger.
Static variables are also always considered GC roots. The objects they reference can be accessed at any time by the class that declared them (or the rest of the program if they are public), so .NET will always keep them around. Variables declared as ‘thread static’ will only last for as long as that thread is running.
If a managed object is passed to an unmanaged COM+ library through interop, then it will also become a GC root with a reference count. This is because COM+ doesn’t do garbage collection: It uses, instead, a reference counting system; once the COM+ library finishes with the object by setting the reference count to 0 it ceases to be a GC root and can be collected again.
If an object has a finalizer, it is not immediately removed when the garbage collector decides it is no longer ‘live’. Instead, it becomes a special kind of root until .NET has called the finalizer method. This means that these objects usually require more than one garbage collection to be removed from memory, as they will survive the first time they are found to be unused.
(emphasis mine)
There're all kinds of root objects, like CLR internal objects, metadata objects, etc. This post may help:
Variables and GC Roots
A variable of a Value Type is direct representation of the address of the Value Type instance on stack
A reference variable to a Value Type instance is called Managed Pointer and is a pointer to the starting address of the Value Type instance on stack
A variable of a Reference Type (UDT, Array, String, Delegate and Interface type variables) is a pointer to the Reference Type instance created on GC heap
CPU registers can contain Managed Pointers or Object References
AppDomain wide Handle tables contain GC handles that are pointers to the pinned Reference Type instances in memory. These Handle tables also contain Managed Pointers (or Object References?) to the static Value Type instances and Object References to the static Reference Type instances
Thread Local Storage (TLS) can contain Object References
FReachable Queue contains Object References of the Reference Types that are NOT referenced by any of the above variable types and for which finalize method call is pending
CLR's Garbage Collector uses the above variables, also called GC roots, to track down the Object References during garbage collection phase. Any Reference Type instance located in GC heap, for which there is no Object Reference in any of the above variable types (except for the FReachable Queue), is considered a candidate for garbage collection and is removed from GC heap. If the Reference Type instance being removed implements the Finalize method, then the Object Reference is put on FReachable Queue for calling the Finalize method by a separate Finalizer thread. Once the Finalizer thread completes Finalize method call on an Object Reference, the corresponding Reference Type instance is removed from the GC heap.
Related
I would like to know if it is possible to execute some C# code when an object is getting destroyed?
I tried to use IDiposable, but my Dispose method is not getting called.
Thanks.
You might be able to do this through Garbage Collection Notification, which allow you to sense and respond when a full garbage collection is approaching and when the full garbage collection has completed.
Garbage Collection Notifications
If an object creates an instance of a type with a finalizer, keeps a reference to that instance, and does not expose that reference to anyone, then when the object holding the only reference becomes eligible for collection, the finalizer of that latter object will be enqueued to run at the next opportunity. Note that the garbage-collector does not run finalizers; it merely adds finalizable objects to a list of things whose finalizers should run as soon as practical. No objects which is on that list, nor any other object to which it holds a direct or indirect strong reference, will be eligible for collection until it ceases to be on that list. If your finalizable object does not hold a reference to the object that holds the reference to it, and if that other object doesn't have a finalizer of its own, that object will be cease to exist once no references exist to it; by the time the finalizer of the latter object runs, the former object won't exist anymore.
I know the knowledge below:
A weak reference permits the garbage collector to collect the object
while still allowing the application to access the object.
So if the object has been reclaimed, you have to create it again when necessary.
Then, what's the difference between short weak reference and long weak reference? I think of it as below:(according to the msdn)
short weak reference: if GC reclaim the object, the object is really
released.
long weak reference: if GC reclaim the object, the object is still
existed (as it is cached).
So can someone tell me more detail?
Short
The target of a short weak reference becomes null when the object is
reclaimed by garbage collection. The weak reference is itself a
managed object, and is subject to garbage collection just like any
other managed object. A short weak reference is the default
constructor for WeakReference.
Long
A long weak reference is retained after the object's Finalize method
has been called. This allows the object to be recreated, but the state
of the object remains unpredictable. To use a long reference, specify
true in the WeakReference constructor.
If the object's type does not have a Finalize method, the short weak
reference functionality applies and the weak reference is valid only
until the target is collected, which can occur anytime after the
finalizer is run.
To establish a strong reference and use the object again, cast the
Target property of a WeakReference to the type of the object. If
the Target property returns null, the object was collected; otherwise,
you can continue to use the object because the application has
regained a strong reference to it.
Guidelines for Using Weak References
Use long weak references only when necessary as the state of the
object is unpredictable after finalization. Avoid using weak
references to small objects because the pointer itself may be as large
or larger.
Avoid using weak references as an automatic solution to memory
management problems. Instead, develop an effective caching policy for
handling your application's objects.
Reference
The .NET Garbage Collector collects objects (reclaims their memory) and also performs memory compaction (to keep memory fragmentation to minimum).
I am wondering, since an application may have many references to objects, how does the GC (or the CLR) manage these references to objects, when the object's address changes due to compaction being made by the GC.
The concept is simple enough, the garbage collector simply updates any object references and re-points them to the moved object.
Implementation is a bit trickier, there is no real difference between native and managed code, they are both machine code. And there's nothing special about an object reference, it is just a pointer at runtime. What's needed is a reliable way for the collector to find these pointers back and recognize them as the kind that reference a managed object. Not just to update them when the pointed-to object gets moved while compacting, also to recognize live references that ensure that an object does not get collected too soon.
That's simple for any object references that are stored in class objects that are stored on the GC heap, the CLR knows the layout of the object and which fields store a pointer. It is not so simple for object references stored on the stack or in a cpu register. Like local variables and method arguments.
The key property of executing managed code which makes it distinct from native code is that the CLR can reliably iterate the stack frames owned by managed code. Done by restricting the kind of code used to setup a stack frame. This is not typically possible in native code, the "frame pointer omission" optimization option is particularly nasty.
Stack frame walking first of all lets it finds object references stored on the stack. And lets it know that the thread is currently executing managed code so that the cpu registers should be checked for references as well. A transition from managed code to native code involves writing a special "cookie" on the stack that the collector recognizes. So it knows that any subsequent stack frames should not be checked because they'll contain random pointer values that don't ever reference a managed object.
You can see this back in the debugger when you enable unmanaged code debugging. Look at the Call Stack window and note the [Native to Managed Transition] and [Managed to Native Transition] annotations. That's the debugger recognizing those cookies. Important for it as well since it needs to know whether or not the Locals window can display anything meaningful. The stack walk is also exposed in the framework, note the StackTrace and StackFrame classes. And it is very important for sandboxing, Code Access Security (CAS) performs stack walks.
For simplicity, I'll assume a stop-the-world GC in which no objects are pinned, every object gets scanned and relocated on every GC cycle, and none of the destinations overlap any of the sources. In actuality, the .NET GC is a bit more complicated, but this should give a good feel for how things work.
Each time a reference is examined, there are three possibilities:
It's null. In that case, no action is required.
It identifies an object whose header says it's something other than a relocation marker (a special kind of object described below). In that case, move the object to a new location and replace the original object with a three-word relocation marker containing the new location, the old location of the object which contains the just-observed reference to the present object, and the offset within that object. Then start scanning the new object (the system can forget about the object that was being scanned for the moment, since it just recorded its address).
It identifies an object whose header says it's a relocation marker. In that case, update the reference being scanned to reflect the new address.
Once the system finishes scanning the present object, it can look at its old location to find out what it was doing before it started scanning the present object.
Once an object has been relocated, the former contents of its first three words will be available at its new location and will no longer be needed at the old one. Because the offset into an object will always be a multiple of four, and individual objects are limited to 2GB each, only a fraction of all possible 32-bit values would be needed to hold all possible offsets. Provided that at least one word in an object's header has at least 2^29 values it can never hold for anything other than an object-relocation marker, and provided every object is allocated at least twelve bytes, it's possible for object scanning to handle any depth of tree without requiring any depth-dependent storage outside the space occupied by old copies of objects whose content is no longer needed.
Garbage collection
Every application has a set of roots. Roots identify storage locations, which refer to objects on the managed heap or to objects that are set to null. For example, all the global and static object pointers in an application are considered part of the application's roots. In addition, any local variable/parameter object pointers on a thread's stack are considered part of the application's roots. Finally, any CPU registers containing pointers to objects in the managed heap are also considered part of the application's roots. The list of active roots is maintained by the just-in-time (JIT) compiler and common language runtime, and is made accessible to the garbage collector's algorithm.
When the garbage collector starts running, it makes the assumption that all objects in the heap are garbage. In other words, it assumes that none of the application's roots refer to any objects in the heap. Now, the garbage collector starts walking the roots and building a graph of all objects reachable from the roots. For example, the garbage collector may locate a global variable that points to an object in the heap.
Once this part of the graph is complete, the garbage collector checks the next root and walks the objects again. As the garbage collector walks from object to object, if it attempts to add an object to the graph that it previously added, then the garbage collector can stop walking down that path. This serves two purposes. First, it helps performance significantly since it doesn't walk through a set of objects more than once. Second, it prevents infinite loops should you have any circular linked lists of objects.
Once all the roots have been checked, the garbage collector's graph contains the set of all objects that are somehow reachable from the application's roots; any objects that are not in the graph are not accessible by the application, and are therefore considered garbage. The garbage collector now walks through the heap linearly, looking for contiguous blocks of garbage objects (now considered free space). The garbage collector then shifts the non-garbage objects down in memory (using the standard memcpy function that you've known for years), removing all of the gaps in the heap. Of course, moving the objects in memory invalidates all pointers to the objects. So the garbage collector must modify the application's roots so that the pointers point to the objects' new locations. In addition, if any object contains a pointer to another object, the garbage collector is responsible for correcting these pointers as well.
C# fixed statement
The fixed statement sets a pointer to a managed variable and "pins" that variable during the execution of statement. Without fixed, pointers to movable managed variables would be of little use since garbage collection could relocate the variables unpredictably. The C# compiler only lets you assign a pointer to a managed variable in a fixed statement.
Garbage Collection: Automatic Memory Management in the Microsoft .NET Framework
fixed Statement (C# Reference)
How do I know an object has no reference to it and at that point it should be deleted by the .NET garbage collector?
I'm doing a number of cloning of an object. The reason why I'm cloning it because it is a same object but it has different values later on. When I unreference the object from a property of some class, I don't know where that certain cloned object is being referenced anywhere in the program. My idea is to definitely know that a certain unreferenced object should not be referenced anywhere. If they are referenced somewhere else, I need to unreference it (fix it).
My idea is to unreference a certain clone of an object everywhere in the system to garbage collect and free up space.
Is there anyway I check this object .NET? Is there any libraries or something like that. I'm feeling the object I think I deleted is still being referenced somewhere in my program while running, because this program is huge. Because it is referenced somewhere else, it is not being garbage collected.
Thanks for your help.
You can use the WeakReference class to hold a reference to your object, and check its IsAlive property to know whether the object still exists or has been gargabe collected (finalized and deallocated). The principal advantage of WeakReference for your case is this reference doesn't prevent the GC to dispose the object target.
You can explicitly invoke the garbage collector before the check to lower the probablity there's no other reference to that object and the GC just didn't notice yet. However, you can't reliably tell whether there is / is not a certain amount of reference to your object 'in the wild'.
I've read some docs about the .NET Garbage Collector but i still have some doubts (examples in C#):
1)Does GC.Collect() call a partial or a full collection?
2)Does a partial collection block the execution of the "victim" application? If yes.. then i suppose this is a very "light" things to do since i'm running a game server that uses 2-3GB of memory and i "never" have execution stops (or i can't see them..).
3)I've read about GC roots but still can't understand how exactly they works. Suppose that this is the code (C#):
MyClass1:
[...]
public List<MyClass2> classList = new List<MyClass2>();
[...]
Main:
main()
{
MyClass1 a = new MyClass1();
MyClass2 b = new MyClass2();
a.classList.Add(b);
b = null;
DoSomeLongWork();
}
Will b ever be eligible to be garbage collected(before the DoSomeLongWork finishes)? The reference to b that classList contains, can it be considered a root?
Or a root is only the first reference to the instance? (i mean, b is the root reference because the instantiation happens there).
There are a couple of overloads for GC.Collect. The one without any parameters does a full collect. But keep in mind that it is rarely a good idea to call GC explicitly.
Garbage collections occurs within a managed application. The GC may have to suspend all managed threads in that process in order to compact the heap. It doesn't affect other processes on the system if that is what you're asking. For most applications it is usually not an issue, but you may experience performance related problems due to frequent collects. There are a couple of relevant performance counters (% time in GC, etc.) that you can use to monitor how the GC is performing.
Think of a root as a valid reference. In your example the instance of MyClass2 will not be collected if there are still references to it. I.e. if the instance pointed to by a is still rooted so will your instance of MyClass2. Also, keep in mind that GC is much more aggressive in release mode builds than debug builds.
GC.Collect() does a full collection. That's why it's not a good idea to call it yourself, as it can prematurely promote objects up a generation
AFAIK, not really. The GC blocks for so little time as to be inconsequential.
A stack GC root is an object that is currently being referenced by a method on the stack. Note that the behaviour is different between debug and release builds; on debug builds all variables in a method are kept alive until the method returns (so you can see their value in the debug window). On release builds the CLR keeps track of where method variables are used and the GC can remove objects that are referenced by the currently executing method but aren't used in the section of the method that is still to execute.
So, in your example, both a and b are not referenced again after the DoSomeLongWork() call, so in release builds, during that method execution they would both be eligible for collection. In debug builds they would hang around until the main() method returns.
Garbage collection is automatic. You don't have to interfere unless you are dealing with unmanaged resources. Garbage gets collected whenever the object is going out of scope; and at specific intervals whenever garbage-collector deems necessary - for instance, OS requires memory. This means there is no guarantee on how soon that will be, but your application will not run out of memory before memory from those objects is reclaimed.
Will b ever be eligible to be garbage collected(before the DoSomeLongWork finishes)?
Yes, whenever garbage collector finds it necessary.
Checkout Garbage Collector Basics and Performance Hints
Yes, GC.Collect() does a full collect, but you can do a manual GC.Collect(0) to do the gen 0 only.
All collections block the threads, but a partial collect does so only very briefly.
No, the instance of MyClass2 is still reachable in the other list. Both a and b are root references (during DoSomeLongWork) but since b is null that doesn't matter. Note that the GC is very tied in with the concept of reference types. b is only a local var referencing the anonymous object. The 'roots' for the GC are static fields, everything on the stack and even CPU registers. In a simpler way: everything your code still has access to.
Will b ever be eligible to be garbage collected (before the DoSomeLongWork finishes)?
Potentially yes, provided a and b are expelled from the set of global roots by the compiler (i.e. not kept on the stack) then they can be reclaimed by a collection during DoSomeLongWork.
I have found cases where .NET reclaims happily but Mono leaks memory.
The reference to b that classList contains, can it be considered a root?
Whether or not b will be turned into a global root depends entirely upon the compiler.
A toy compiler might push references from function arguments and returned from function calls onto the stack and unwind the stack at the end of each function. In this case, b will be pushed onto the stack and, therefore, will be a global root.
Production quality compilers perform sophisticated register allocation and maintain only live references on the stack, either overwriting or nulling references on the stack as they die. In this case, b is dead during the call to DoSomeLongWork so its stack entry will have been nulled or overwritten.
None of this can be inferred from the source code without details of what exactly the compiler will do. For example, my HLVM project is only a toy at this stage, using the former technique, but it will actually collect a and b in this case because the call to DoSomeLongWork is a tail call.
Or a root is only the first reference to the instance?
The global roots are the references the GC begins with in order to traverse all of the reachable data in the heap. The global roots are typically global variables and threads' stacks but more sophisticated GC algorithms can introduce new kinds of global roots, e.g. remembered sets.