How to explicitly clear a byte []

I create new byte arrays that are not collected by the GC and live in memory and increase private bytes. The following code runs every 10 seconds. How to explicitly clear a variable after I have finished with it?

byte[] outputMessage = new byte[10000]; //Do some work here 
+7
source share
6 answers

How do you know that they are not going to? The code you provide is in order and should be suitable for collection if you do not have any dangling links to it.

Explicitly, you can clear the link

 outputMessage = null; 

and you can hint to GC that he should do his job with this:

 GC.Collect(); 

However, there is no guarantee that your object will be assembled, and manual interaction with the GC is usually not required.

If you add a new event handler all the time, do you delete any old ones? If not, they still save the link for you.

EDIT: for clarity and for new OP information

+9
source

Make sure you have no references to your array. Make sure you don’t have an assignment to another variable that stores the array in memory.

Do you leave the focus of your outputMessage?
- If it is declared inside the method: will you leave it or do you have (intendet) an infinite loop and remain in it?
- If it is declared global inside a class object: does your full class remain in memory by reference to this?

+2
source

It is hard to say for sure without seeing the context in which they are used. If you do not keep links to each outputMessage message, they will receive garbage collected ultimately whenever the GC decides to start.

What did you look at that private bytes continued to grow and never contracted? Also, did you work only with a debugger connected or running in the release?

Do you really need to create a new array every 10 seconds? It can be faster just Array.Clear and reuse it.

+2
source

Consider this: is it possible to encapsulate your byte [] in a class that implements IDisposable? After use, you can destroy your object by explicitly specifying Dispose (). I am not sure if this will help you solve the problem, but this will be my next attempt.

+2
source

When the managed array leaves its scope, it becomes marked for garbage collection. If the array is of type value, the release of elements occurs quickly, but does not occur until the array is assembled. Remember that byte is a value type, but byte[] is a reference type.

Here is an example that shows:

 void Main() { const int LOOPS = 5; { Console.WriteLine("When the arrays are kept inside the method scope:"); Console.WriteLine(String.Format(" GC Memory: {0:N0} bytes (starting memory)", GC.GetTotalMemory(false))); for(int i = 0; i < LOOPS; i++) this.AllocateArray(i); Console.WriteLine(String.Format(" GC Memory: {0:N0} bytes (exited local scope)", GC.GetTotalMemory(false))); Console.WriteLine(String.Format(" GC Memory: {0:N0} bytes (after GC collection ran)", GC.GetTotalMemory(true))); Console.WriteLine("\nWhen the arrays are outside the method scope:"); Console.WriteLine(String.Format(" GC Memory: {0:N0} bytes (starting memory)", GC.GetTotalMemory(false))); var arrays = new byte[LOOPS][]; for(int i = 0; i < LOOPS; i++) this.AllocateArray(i, arrays); Console.WriteLine(String.Format(" GC Memory: {0:N0} bytes (exited local scope)", GC.GetTotalMemory(false))); Console.WriteLine(String.Format(" GC Memory: {0:N0} bytes (after GC collection ran)", GC.GetTotalMemory(true))); arrays[0][0] = 1; // Prevent the arrays from being optimized away } Console.WriteLine("\nAll scopes exited:"); Console.WriteLine(String.Format(" GC Memory: {0:N0} bytes (before GC runs)", GC.GetTotalMemory(false))); Console.WriteLine(String.Format(" GC Memory: {0:N0} bytes (after GC collection ran)", GC.GetTotalMemory(true))); } public void AllocateArray(int run) { var array = new byte[20000000]; Thread.Sleep(100); // Simulate work.. Console.WriteLine(String.Format("[{0}] GC Memory: {1:N0} bytes (local array allocated)", run+1, GC.GetTotalMemory(false))); array[0] = 1; // Prevent the array from being optimized away } public void AllocateArray(int run, byte[][] arrays) { arrays[run] = new byte[20000000]; Thread.Sleep(100); // Simulate work.. Console.WriteLine(String.Format("[{0}] GC Memory: {1:N0} bytes (array allocated)", run+1, GC.GetTotalMemory(false))); } 

The result from this looks something like this (the exact results will vary):


When arrays are stored inside the method area: GC memory: 24,576,232 bytes (initial memory)
[1] GC memory: 45 002 324 bytes (local array allocated)
[2] GC memory: 44,845,548 bytes (local array allocated)
[3] GC memory: 64,574,296 bytes (local array allocated)
[4] GC memory: 64,959,472 bytes (local array allocated)
[5] GC memory: 44,675,340 bytes (local array allocated) GC memory: 44,675,340 bytes (leaving the local area) GC Memory: 24,347,296 bytes (after starting the GC collection)


When arrays are outside the scope of the method: GC-memory: 24 355 488 bytes (initial memory)
[1] GC memory: 44,467,612 bytes (dedicated matrix)
[2] GC Memory: 64,681,980 bytes (array allocation)
[3] GC memory: 85,493,004 bytes (allocated by array)
[4] GC memory: 104,442,028 bytes (dedicated matrix)
[5] GC memory: 124,450,236 bytes (array allocated) GC memory: 124,450,236 bytes (leaving the local area) GC Memory: 124 357 588 bytes (after starting the GC collection)


All output areas: GC Memory: 124,365,780 bytes (before starting the GC) GC: 24,356,996 bytes (after starting the GC collection)

To solve your problem:

  • Make sure that you do not match links to byte[] s. Bytes will not be cleared until all array references are complete and it is completely out of scope.
  • Call GC.Collect() explicitly after you leave the byte array area. once it goes out of scope, byte[] will clear itself, but you can tell it to execute instead of waiting.
+2
source

This test case only works in release mode. I create an array using the guid class (this is easy). There would be 16 elements.

 [TestMethod] public void ByteArrayReleasesMemoryWhenTheyGoOutOfScope() { // *** WORKS ONLY IN RELEASE MODE *** // arrange var weakRef = new WeakReference(null); // easy way to generate byte array var byteArray = Guid.NewGuid().ToByteArray(); weakRef.Target = byteArray; // act GC.Collect(); GC.WaitForPendingFinalizers(); GC.Collect(); // assert Assert.IsFalse(weakRef.IsAlive); } 
0
source

All Articles