all groups > dotnet clr > may 2007 >
You're in the dotnet clr group:
Brackets in C#
dotnet clr:
Is it true that the IL language doesn't include the concept of brackets ("{", "}") and they have merely semantic meaning? If so, how does the C# compiler handle them? (Perhaps it uses the "}" sign to inject code that unreferences all object instances defined within the scope of the braces?).
[quoted text, click to view] >Is it true that the IL language doesn't include the concept of brackets ("{", >"}") and they have merely semantic meaning?
They are used in IL assembler as well, but not necessarily in the same way as in C#. [quoted text, click to view] >If so, how does the C# compiler handle them? (Perhaps it uses the "}" sign >to inject code that unreferences all object instances defined within the >scope of the braces?).
In which context? Curly braces are used in a number of places in the C# language. Variables are not automatically set to null when you leave a scope if that's what you mean. Mattias -- Mattias Sjögren [C# MVP] mattias @ mvps.org http://www.msjogren.net/dotnet/ | http://www.dotnetinterop.com
Thanks. Another question: is it a good practice to set these objects' references to null manually once I no longer use them? (So that the GC could claim them). Or perhaps I shouldn't worry about such stuff? [quoted text, click to view] "Mattias Sjögren" wrote: > > >Is it true that the IL language doesn't include the concept of brackets ("{", > >"}") and they have merely semantic meaning? > > They are used in IL assembler as well, but not necessarily in the same > way as in C#. > > > >If so, how does the C# compiler handle them? (Perhaps it uses the "}" sign > >to inject code that unreferences all object instances defined within the > >scope of the braces?). > > In which context? Curly braces are used in a number of places in the > C# language. > > Variables are not automatically set to null when you leave a scope if > that's what you mean. > > > Mattias > > -- > Mattias Sjögren [C# MVP] mattias @ mvps.org > http://www.msjogren.net/dotnet/ | http://www.dotnetinterop.com > Please reply only to the newsgroup.
[quoted text, click to view] >Another question: is it a good practice to set these objects' references to >null manually once I no longer use them? (So that the GC could claim them). >Or perhaps I shouldn't worry about such stuff?
No you usually don't have to do that. Mattias -- Mattias Sjögren [C# MVP] mattias @ mvps.org http://www.msjogren.net/dotnet/ | http://www.dotnetinterop.com
Why not? Is it not possible that the GC will be triggered before I exit the method? (Which means all unused objects, defined within the scope of the method, will still be referenced and will reach generation 1 or 2). [quoted text, click to view] "Mattias Sjögren" wrote: > >Another question: is it a good practice to set these objects' references to > >null manually once I no longer use them? (So that the GC could claim them). > >Or perhaps I shouldn't worry about such stuff? > > No you usually don't have to do that. > > > Mattias > > -- > Mattias Sjögren [C# MVP] mattias @ mvps.org > http://www.msjogren.net/dotnet/ | http://www.dotnetinterop.com > Please reply only to the newsgroup.
Hi Amir! [quoted text, click to view] > Is it not possible that the GC will be triggered before I exit the > method?
Yes (in Release-Builds). [quoted text, click to view] > (Which means all unused objects, defined within the scope of > the method, will still be referenced and will reach generation 1 or > 2).
The point is: "Unused" is tracked by Root-References, not be Reference-Counting. So setting an Object-Reference (located on the Stack) to null will not cause the Object behind the Reference to be collected. It may be even later, because setting an Object-Reference is also an Operation with the Reference, so without setting the Reference to null, the Object could have been collected immediatly. Worst Example: try{ Foo x = new Foo(); x.LastUsage(); // some other long-running code } finally { x = null; } In this case you won't help the CLR in any way. Without "x = null" the CLR could collect the Foo - Instance very earlier. Another Example: Foo x = new Foo(); x.LastUsage(); x = null; // some other long-running code In this case, there is still a (theoretical) time-slide when the GC could act earlier without setting x to null, but (even it will not be significant), you will win nothing in any case, it's just an unnessersary line of code. GP
My point is that if the local variables of a method aren't considered as root references, what prevents the GC from collection local objects prematurely? Meaning, how does the GC knows (if at all) when do I stop using an object inside a method's body? [quoted text, click to view] "Günter Prossliner" wrote: > Hi Amir! > > > > Is it not possible that the GC will be triggered before I exit the > > method? > > Yes (in Release-Builds). > > > (Which means all unused objects, defined within the scope of > > the method, will still be referenced and will reach generation 1 or > > 2). > > The point is: "Unused" is tracked by Root-References, not be > Reference-Counting. So setting an Object-Reference (located on the Stack) to > null will not cause the Object behind the Reference to be collected. It may > be even later, because setting an Object-Reference is also an Operation with > the Reference, so without setting the Reference to null, the Object could > have been collected immediatly. > > Worst Example: > try{ > Foo x = new Foo(); > x.LastUsage(); > > // some other long-running code > } finally { > x = null; > } > > In this case you won't help the CLR in any way. Without "x = null" the CLR > could collect the Foo - Instance very earlier. > > Another Example: > Foo x = new Foo(); > x.LastUsage(); > x = null; > > // some other long-running code > > In this case, there is still a (theoretical) time-slide when the GC could > act earlier without setting x to null, but (even it will not be > significant), you will win nothing in any case, it's just an unnessersary > line of code. > > > > > GP > >
[quoted text, click to view] "Amir Shitrit" <AmirShitrit@discussions.microsoft.com> wrote in message news:5A7D56BC-FA2B-41BC-9DB1-8F46BC07D1CF@microsoft.com... > My point is that if the local variables of a method aren't considered as > root > references, what prevents the GC from collection local objects > prematurely? > Meaning, how does the GC knows (if at all) when do I stop using an object > inside a method's body?
Because reflection against local variables is not possible, they really are scoped to the enclosing function. Therefore, the compiler can analyze which locals are used by which instructions, and determine the usable lifetime of those variables precisely. I've seen several demos where the GC collects a object referenced by a local variable that is in scope but dead (not mentioned again). [quoted text, click to view] > > "Günter Prossliner" wrote: > >> Hi Amir! >> >> >> > Is it not possible that the GC will be triggered before I exit the >> > method? >> >> Yes (in Release-Builds). >> >> > (Which means all unused objects, defined within the scope of >> > the method, will still be referenced and will reach generation 1 or >> > 2). >> >> The point is: "Unused" is tracked by Root-References, not be >> Reference-Counting. So setting an Object-Reference (located on the Stack) >> to >> null will not cause the Object behind the Reference to be collected. It >> may >> be even later, because setting an Object-Reference is also an Operation >> with >> the Reference, so without setting the Reference to null, the Object could >> have been collected immediatly. >> >> Worst Example: >> try{ >> Foo x = new Foo(); >> x.LastUsage(); >> >> // some other long-running code >> } finally { >> x = null; >> } >> >> In this case you won't help the CLR in any way. Without "x = null" the >> CLR >> could collect the Foo - Instance very earlier. >> >> Another Example: >> Foo x = new Foo(); >> x.LastUsage(); >> x = null; >> >> // some other long-running code >> >> In this case, there is still a (theoretical) time-slide when the GC could >> act earlier without setting x to null, but (even it will not be >> significant), you will win nothing in any case, it's just an unnessersary >> line of code. >> >> >> >> >> GP >> >> >>
[quoted text, click to view] <"G=FCnter Prossliner" <g.prossliner/gmx/at>> wrote:
<snip> [quoted text, click to view] > Worst Example: > try{ > Foo x =3D new Foo(); > x.LastUsage(); >=20 > // some other long-running code > } finally { > x =3D null; > } >=20 > In this case you won't help the CLR in any way. Without "x =3D null" the = CLR=20 > could collect the Foo - Instance very earlier.
<snip> No - the CLR detects that the assignment doesn't count as "reading" the=20 variable, so it can still collect the instance before the x=3Dnull; line=20 would be executed. --=20 Jon Skeet - <skeet@pobox.com> http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet
[quoted text, click to view] Amir Shitrit <AmirShitrit@discussions.microsoft.com> wrote: > My point is that if the local variables of a method aren't considered as root > references, what prevents the GC from collection local objects prematurely?
They *are* considered root references, but only to the point of the last possible read. [quoted text, click to view] > Meaning, how does the GC knows (if at all) when do I stop using an object > inside a method's body?
Because it can analyse the IL and spot that there's no code in the rest of the method that will read the variable's value. -- Jon Skeet - <skeet@pobox.com> http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet
Hi Amir! [quoted text, click to view] > My point is that if the local variables of a method aren't considered > as root references, what prevents the GC from collection local > objects prematurely? Meaning, how does the GC knows (if at all) when > do I stop using an object inside a method's body?
Stack - References are only considered as Roots when they are accessed after the current Execution-Pointer (as Jon pointed out, only read-access in encountered). Allthough AFIAK there is nothing about this in the official docs (specs), but there are articles where this behavior was been described: http://msdn.microsoft.com/msdnmag/issues/1100/GCI/default.aspx "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" The GC gets this information from the JIT-Compiler, there is no need to inject code. GP
But how exactly does the CLR know when it's safe to collect it? Does it inject some code to do so? [quoted text, click to view] "Jon Skeet [C# MVP]" wrote: > <"Günter Prossliner" <g.prossliner/gmx/at>> wrote: > > <snip> > > > Worst Example: > > try{ > > Foo x = new Foo(); > > x.LastUsage(); > > > > // some other long-running code > > } finally { > > x = null; > > } > > > > In this case you won't help the CLR in any way. Without "x = null" the CLR > > could collect the Foo - Instance very earlier. > > <snip> > > No - the CLR detects that the assignment doesn't count as "reading" the > variable, so it can still collect the instance before the x=null; line > would be executed. > > -- > Jon Skeet - <skeet@pobox.com> > http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet > If replying to the group, please do not mail me too
[quoted text, click to view] "Amir Shitrit" <AmirShitrit@discussions.microsoft.com> wrote in message news:9E05FB3A-D22E-4CB5-A4C2-3A4659F4F063@microsoft.com... > But how exactly does the CLR know when it's safe to collect it? > Does it inject some code to do so?
The JIT generates some mapping from instruction pointer to information on stack-local roots. The GC suspends all other threads, and then walks the call stack of each, inspecting the stack-local roots that the JIT indicated were being used at the current location (in addition to global roots, basically the list of System.Type objects maintained by the runtime, which reach each constructed Type, which reach the static members, and so on). Naturally not all local variables are roots, an int for example is the right size on 32-bit, but doesn't represent the address of a managed object instance, so the GC needn't consider it. [quoted text, click to view] > > "Jon Skeet [C# MVP]" wrote: > >> <"Günter Prossliner" <g.prossliner/gmx/at>> wrote: >> >> <snip> >> >> > Worst Example: >> > try{ >> > Foo x = new Foo(); >> > x.LastUsage(); >> > >> > // some other long-running code >> > } finally { >> > x = null; >> > } >> > >> > In this case you won't help the CLR in any way. Without "x = null" the >> > CLR >> > could collect the Foo - Instance very earlier. >> >> <snip> >> >> No - the CLR detects that the assignment doesn't count as "reading" the >> variable, so it can still collect the instance before the x=null; line >> would be executed. >> >> -- >> Jon Skeet - <skeet@pobox.com> >> http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet >> If replying to the group, please do not mail me too >>
[quoted text, click to view] Amir Shitrit wrote: > But how exactly does the CLR know when it's safe to collect it? > Does it inject some code to do so? > > "Jon Skeet [C# MVP]" wrote: >
The code is analyzed at compilation, so the CLR knows the "usage span" of each variable. There is no code injected for garbage collection. There is absolutely nothing extra that is happening when a variable goes out ot scope or "usage span". Only the garbage collector knows about things like this, the rest of the code has no clue. -- Göran Andersson _____
Don't see what you're looking for? Try a search.
|
|
|