The whole purpose of a Garbage Collection
Once a class is defined, you can allocate any number of objects using the C# new keyword. Understand, however, that the new keyword returns a reference to the object on the heap, not the actual object itself. This reference variable is stored on the stack for further use in your application. When you wish to invoke members on the object, apply the C# dot operator to the stored reference.
When you are building your C# application, you are correct to assume that the managed heap will take care of itself without direct intervention. In fact, the golden rule of .NET memory management is simple:
Allocate an object onto the managed heap using the new keyword and forget about it
Once instantiated, the garbage collector will destroy the object when it is no longer needed. The next obvious question, of course, is “How does the garbage collector determine when an object is no longer needed?”
The answer is that the garbage collector removes an object from the heap when it is “unreachable” by any part of your code base.
Assume you have a method in your Program class that allocate a local IceCream object:
Notice that the IceCream reference (iceCream) has been created directly within the “MakeAnIceCream” method and has not been passed outside of the defining scope. Thus, once this method call completes, the iceCream reference is no longer reachable, and the associated IceCream object is now a candidate for garbage collection. Understand, however, that you cannot guarantee that this object will be reclaimed from the memory immediately after MakeAnIcreCream() has completed. All you can assume at this point is that when the CLR performs the next garbage collection, the iceCream object could be safely destroyed.
The base class libraries provide a class type named System.GC that allows you to programmatically interact with the garbage collector using a set of static members. Typically speaking, the only time you will make use of this type directly is when you are creating types that makes use of unmanaged resources.
The whole purpose of the .NET Garbage collector is to manage memory on your behalf. However, under some very rare circumstances, it may be beneficial to programmatically force a garbage collection using GC.Collect(), specifically:
-
Your application is about to enter into a block of code that you do not wish to be interrupted by a possible garbage collection.
-
Your application has just finished allocating an extremely large numbers of objects and you wish to remove as much of the acquired memory as possible.
If this is the case it may be beneficial to have the garbage collector check for unreachable objects, you could explicitly trigger a garbage collection as follows:
When you manually force a garbage collection, you should always make a call to GC.WaitForPendingFinalizers(). With this approach, you can rest assured that all finalizable objects have had a chance to perform any necessary cleanup before your program continues forward. Under the hood, GC.WaitForPendingFinalizers() will suspend the calling thread during the collection process. This is a good thing as it ensures your code does not invoke methods on an object currently being destroyed.
The GC.Collect() method can also be supplied a numerical value that identifies the oldest generation on which a garbage collection will be performed. For example, you wished to instruct the CLR to only investigate generation 0 objects, you should write the following:
As well, as of .NET 3.5, the Collect() method can also be passed in a value of the GCCollectionMode enumeration as a second parameter, to fine-up exactly how the runtime should force the garbage collection. This enum defines the following values:
Now, back to the topic of how the garbage collector determines when an object is “no longer needed”. To understand the details, you need to be aware of the notion of application roots. Simply put, a root is a storage location containing a reference to an object on the heap. Stricly speaking, a root can fall into any of the following categories:
- References to global objects
- Reference to any static objects / static fields
- Reference to local objects within an application’s code base
- Reference to object parameters passed into a method
- References to objects waiting to be finalized
- Any CPU register that references an object
During a garbage collection process, the runtime will investigate objects on the managed heap to determine whether they are still reachable (aka rooted) by the application. To do so, the CLR will build an object graph, which represent each reachable object on the heap. Object graphs are used to document all reachable objects. As well, the garbage collector will never graph the same object twice.
Assume the managed heap contains a set of objects named A,B,C,D,E,F and G. During a garbage collection, these objects are examined for active roots. Once the graph has been constructed, unreachable objects are marked as garbage.
Once an object has been marked for the termination (C and F in this case) they are swept from memory. At this point, the remaining space on the heap is compacted, which in turn will cause the CLR to modify the set of active applications roots (and the underlying pointers) to refer to the correct memory location (this is done automatically and transparently). Last but not least, the next object pointer is readjusted to point to the next available slot.
Hardcore code validation
private bool IsCleaned(string untrustedText)
{
System.Text.ASCIIEncoding encoding =new System.Text.ASCIIEncoding();
bool iscleaned = false;
foreach (byte chunk in encoding.GetBytes(untrustedText)) {
// 60 = < | 62 = > |45 = - | 39 = '
if ((chunk == 60) || (chunk == 62) || (chunk == 45) || (chunk == 39)) {
iscleaned = false;
break;
}
else { iscleaned = true; }
}
return iscleaned;
}
OWASP goes Open Source (for real)
Code Crawler is now on CodePlex. It has been classified with the following keywords : CodeReview, C#. At the moment I decided to mark the project as Setup which means that the content that will be illustrated is still not available.
From tomorrow on the development will be shifted to CodePlex. Every file related to CodeCrawler previously hosted on cyphersec.com has already been deleted (Sorry for that had no choice).
Also a new beta release version will be linked from the main page which will include a couple of new features.
- Increase stability
- OWASP Code Guidelines support
- Threat Analysis
Current Development Scenario:
In the next two weeks the Grid control used to list all the threats found in your file will be replaced by a new control (BUGID#931 Priority: Medium).
A new functionality will be also included which will make code crawler and advanced tool capable of crawling web applications affected by traversal path vulnerabilities (FEATUREID#940 Priority:Medium).
The Reporting UI will be redesigned from scratch. There is no reason to replace the reporting engine since it has reached a stable version. CC will keep supporting XSLT as standard for the reports area until new "polished" alternatives are proposed and , from a development prospective , well-integrated.
XML Engine and threats discover to be (20% at least) faster. Cracking the system using .NET 3.5 enhancements
Enhance Welcome Screen (BUGID#928 Priority:Medium); Code Crawler will be fully refined using a combination of black and gray colours. A mix of BlackBerry Style and Windows Vista Ultimate themes.
Implicitly Typed Local Variables in C# 2008.
Con il rilascio di C# 2008 e la piattaforma .NET 3.5 in generale, nuove features per la manipolazione dei dati sono state introdotte.
In particolare C# 2008 continua ad essere il linguaggio ad aver ricevuto alcune delle piu' interessanti.
Come sempre e' bene ricordare che .NET 3.5 e' .NET 2.0 piu' <qualcosa>; Quindi i sistemi legacy sono ancora validi ma, sconsigliati in termini di performance (95%) e rapporto developer/tempo.
Per esempio in C# 2008 e' possibile dichiarare variabili in modo implicito anziche' esplicito. Sembra una cosa da poco, ma e' molto interessante capirne il concetto per utilizzarle al meglio e trarne il maggior guadagno.
Allora, prendete qualunque programmatore C# e chiedetegli di dichiararvi tre variabili (int,string,boolean). Il 99% rispondera' cosi'
class Program
{
static void Main(string[] args)
{
// int32
int TypeInteger = 0;
// string
string TypeString = string.Empty;
// bool
bool TypeBool = false;
}
}
Questo modo di dichiarare le variabili si chiama "Esplicito". Ora con C# e' possibile fare esattamente lo stesso solo in modalita' Implicita.
class Program
{
static void Main(string[] args)
{
var TypeInteger = 0; // Integer
var TypeString = "alessio"; // String
var TypeBool = false; // Boolean
}
}
Quando questo si verifica il compilatore dedurra' il tipo di dell'oggetto che sta "valorizzando" la variabile e quindi dichiarera' quest'ultima con il corrispondente tipo.
In questo caso qui sopra, TypeInteger sara' un System.Int32, TypeString sara' System.String e TypeBool sara' System.Boolean. Per verificare questo e' possibile scrivere il seguente codice.
class Program
{
static void Main(string[] args)
{
var TypeInteger = 0; // Integer
var TypeString = "alessio"; // String
var TypeBool = false; // Boolean
Console.WriteLine("TypeInteger is a: {0}", TypeInteger.GetType().Name);
Console.WriteLine("TypeString is a: {0}", TypeString.GetType().Name);
Console.WriteLine("TypeBool is a: {0}", TypeBool.GetType().Name);
Console.ReadLine();
}
}
Naturalmente si puo' effettuare questo anche con tutti gli oggetti .NET come Custom Types, List, Arrays etc. E' possibile fare uso della keyword var anche in cicli foreach. Per esempio
class Program
{
static void Main(string[] args)
{
var numeriPari = new int[] { 2, 4, 6, 8 };
foreach (var singoloNumeroEstratto in numeriPari)
{
Console.WriteLine("Valore: {0}", singoloNumeroEstratto);
}
}
}
Da ricordare che fare uso di keyword var in cicli foreach e' altamente sconsigliato in termini di performance. In qualunque operazione di iterazione l'utilizzo di iteratori base 32 int e' consigliata per via del fatto che questi sono ottimizzati hardware.
La conversione implicita di dati in C# 2008 ha comunque delle restrizioni. <Questo e' importante>.
Per prima cosa si deve tenere a mente che e' possibile eseguirlo solo ed unicamente su variabili locali, metodi o proprieta'.
- var non puo' essere nullable.
- var non puo' essere un: return value, parameter, field data type.
Vantaggi:
Var porta lo Strong Data Typing dove prima non esisteva.
La filosofia .NET 3.5 tende a ridurre a zero il boxing per via del semplice fatto che Object era l'unica risposta in molti casi. Oggi con .NET e' possibile sistemi che si astraggono dai stati primitivi di programmazione. Man mano che si procede nelle certificazioni Visual Studio 2008 si nota come Microsoft abbia cercato di dare la possibilita' di far guadagnare piu' tempo ai sviluppatori lasciandoli lavorare piu' sul Object Oriented invece che fargli scornare con problematiche inutili.
La piattaforma Microsoft nasce e resta una tecnologia per il BUSINESS. Per questo ora in .NET e' possibile lavorare con entita' di cui non si conosce il tipo. Tutto si sta trasformando in entita' (e' su questa filosifia che e' nato Entity Framework (prima dai Generics poi dai var etc).
var si rende utile quando si lavora con collezioni di cui non si ha controllo. Vedi Linq.
Faccio un esempio veloce cosi' si arriva velocemente a capire il concetto.
Il seguente snippet e' di Andrew Troelsen e dimostra perfettamente l'importanza di var.
static void Main(string[] args)
{
int[] numbers = { 10,20,30,40,1,2,3,8};
var subset = from i in numbers where i > 8 select i;
Console.WriteLine("Values in subset: ");
foreach (var i in subset)
{
Console.WriteLine("{0} :", i);
}
Console.WriteLine();
// Hmm... what type is subset?
Console.WriteLine("subset is a: {0}", subset.GetType().Name);
Console.ReadLine();
}
Ritorna :
Values in subset:
10 :
20 :
30 :
40 :
subset is a: <WhereIterator>d__0`1
subset is defined in: <WhereIterator>d__0`1
chi avrebbe detto un array di integers e' bocciato