Common memory leaks and solutions in. NET, and. net leakage Solutions
In. NET, although the clr gc Garbage Collector helps us automatically recycle managed heap objects and release the memory, the "Memory leakage" is avoided to the greatest extent (the memory occupied by the application is not released in time),. NET application "Memory leakage" still exists. If you do not pay attention to it, "Memory leakage" may occur from time to time.
Memory leakage caused by stream and Reader or Writer
For example, read the file to the stream:
public static string ReadFile()
{
Var filePath = @ "Hard Disk address ";
var sr = new StreamReader(filePath);
return sr.ReadToEnd();
}
As shown above, StreamReader does not interpret and destroy the data after reading the data, resulting in "Memory leakage ". The correct method is to close it immediately after use.
public static string ReadFile()
{
Var filePath = @ "Hard Disk address ";
using(var sr = new StreamReader(filePath))
{
return sr.ReadToEnd();
}
}
Or
public static string ReadFile()
{
Var filePath = @ "Hard Disk address ";
var sr = new StreamReader(filePath);
var result = sr.ReadToEnd();
sr.Close();
return result;
}
Note that when an object instance is created through a stream constructor, close it in time.
Sometimes, if you return an object instance of a stream through a method, you will forget to close it. For example:
// Create a byte array
var data = new byte[1024];
var client = new TcpClient();
// Return the stream from the TCP instance method
var stream = client.GetStream();
// Read the stream to the byte array
int bytesLength = stream.Read(data, 0, data.Length);
// Convert the byte array to the city string
var result = System.Text.Encoding.ASCII.GetString(data, 0, bytesLength);
The correct statement should be:
// Create a byte array
var data = new byte[1024];
var client = new TcpClient();
// Return the stream from the TCP instance method
var stream = client.GetStream();
// Read the stream to the byte array
int bytesLength = stream.Read(data, 0, data.Length);
stream.Close();
// Convert the byte array to the city string
var result = System.Text.Encoding.ASCII.GetString(data, 0, bytesLength);
Similarly, for other stream-related classes, we also need to disable them in time after they are used up:
● FileStream
● MemoryStream
● StreamReader
● TextWriter
......
Memory leakage caused by static reference
For static instances, the corresponding memory will not be released unless the application is closed. For example, the following classes follow the "Siingleton" mode (thread security is not considered ).
public class MySingletonClass
{
private static MySingletonClass myInstance;
private static List<IAmBig> bigObjects = new List<IAmBig>();
private MySingletonClass(){}
public static MySingletonClass MyInstance
{
get
{
if(myInstance == null)
{
myInstance = new MySingletonClass();
}
return myInstance;
}
}
public static IAmBig CreateBigObject()
{
var bigObject = new IAmBig();
bigobject.AllocateMemory(4096);
bigObjects.add(bigObject);
return bigObject;
}
}
public class IAmBig
{
}
The above Code adds the CreateBigObject static method to the List <IAmBig> type set every time you call the CreateBigObject static method. Because the MySingletonClass static class instance remains in the life cycle of the application, in addition, GC does not release the bigObjects collection object instance, so a "memory leak" occurs ". The solution is to prevent static instances from referencing other instance objects and avoid chained references of static instances.
Memory leakage caused by Delegation
For example, there are two delegated chains.
var objectOne = new ObjectOne();
var objectTwo = new ObjectTwo();
objectOne.StateChanged += objectTwo.StateChangedEventHandler;
objectTwo.Dispose();
The above code registers the objectTwo delegate to objectOne. In this way, objectOne and objectTwo are dependent and form a dependency chain. ObjectTwo can be released only when objectOne is released. If objectOne happens to be a global static instance, objectTwo will not be able to release the memory during the application lifecycle, resulting in "Memory leakage ".
The solution is to unbind the dependency between the two before calling the Dispose method of objectTwo. Modify as follows:
var objectOne = new ObjectOne();
var objectTwo = new ObjectTwo();
objectOne.StateChanged += objectTwo.StateChangedEventHandler;
......
objectOne.StateChanged -= objectTwo.StateChangedEventHandler;
objectTwo.Dispose();
Memory leakage caused by unmanaged Resources
public class MyUnManagedExample
{
public void Allocate()
{
IntPtr pointer = Marshal.AllocHGlobal(1024);
}
}
You must release the created unmanaged instance ponter explicitly.
Marshal.FreeGlobal(pointer);
Memory leakage caused by classes implementing the IDisposable Interface
All classes that implement the IDisposable interface have a Dispose method. If you forget to call the method, it will cause "Memory leakage ".