Main Site Documentation

GC memory error


#1

Hello everyone,
I’m using GLIDE in my code. What I’m trying to implement is a simple window that displays current date and time…
Very trivial, I agree, but the problem is not related to the implementation itself, the problem is that when I leave my code running for a while, approximately one or two hours, I receive this message on the Visual studio 2013 debug window:

GC: 11msec 1911324 bytes used, 5428344 bytes available
Type 0F (STRING              ):   2376 bytes
Type 11 (CLASS               ):  15516 bytes
Type 12 (VALUETYPE           ):   4368 bytes
Type 13 (SZARRAY             ):  11184 bytes
  Type 01 (BOOLEAN             ):     84 bytes
  Type 03 (U1                  ):   2628 bytes
  Type 04 (CHAR                ):    492 bytes
  Type 07 (I4                  ):   1008 bytes
  Type 0F (STRING              ):   1944 bytes
  Type 11 (CLASS               ):   4608 bytes
  Type 12 (VALUETYPE           ):    420 bytes
Type 15 (FREEBLOCK           ): 5428344 bytes
Type 16 (CACHEDBLOCK         ):    108 bytes
Type 17 (ASSEMBLY            ):  35976 bytes
Type 18 (WEAKCLASS           ):    192 bytes
Type 19 (REFLECTION          ):    216 bytes
Type 1B (DELEGATE_HEAD       ):   1152 bytes
Type 1C (DELEGATELIST_HEAD   ):    384 bytes
Type 1D (OBJECT_TO_EVENT     ):    120 bytes
Type 1E (BINARY_BLOB_HEAD    ): 1828692 bytes
Type 1F (THREAD              ):   1152 bytes
Type 20 (SUBTHREAD           ):    144 bytes
Type 21 (STACK_FRAME         ):   5268 bytes
Type 27 (FINALIZER_HEAD      ):    312 bytes
Type 31 (IO_PORT             ):     72 bytes
Type 33 (I2C_XACTION         ):     48 bytes
Type 34 (APPDOMAIN_HEAD      ):     72 bytes
Type 36 (APPDOMAIN_ASSEMBLY  ):   3972 bytes

And after this the board becomes completely unresponsive to touches.

What could cause this strange behaviour ? If i understand correctly, there shouldn’t be any memory problem, as it says that there are 1911324 bytes used vs 5428344 bytes available…

I really don’t know what to do, I tried to force GC to run (Debug.GC(true)) and to suppress the GC debug messages, but nothing changed…

Thanks,
Matteo.

P. S.: I’m using a Fez Cobra ||| board.


#2

Update:

I tried to write a plain NETMF app that only displays the current date/time, plus a black rectangle on the screen:

using System;

using Microsoft.SPOT;
using Microsoft.SPOT.Input;
using Microsoft.SPOT.Presentation;
using Microsoft.SPOT.Presentation.Controls;
using Microsoft.SPOT.Presentation.Media;

namespace Test
{
public class TestWindow : Window
{
    public Text time = new Text();
    public Panel panel = new Panel();
    private DispatcherTimer clockTimer;

    public TestWindow() : base()
    {
        time.Font = Resources.GetFont(Resources.FontResources.small);
        time.TextContent = DateTime.Now.ToString("MM/dd/yyyy hh:mm:ss");
        time.HorizontalAlignment = HorizontalAlignment.Right;
        time.VerticalAlignment = VerticalAlignment.Bottom;

        clockTimer = new DispatcherTimer(this.Dispatcher);
        clockTimer.Interval = new TimeSpan(0, 0, 0, 1, 0);
        clockTimer.Tick += new EventHandler(ClockTimer_Tick);

        // Add the time control to the window.
        this.Child = panel;
        panel.Children.Add(time);

        clockTimer.Start();
        // Make the window visible and the size of the LCD
        this.Visibility = Visibility.Visible;
        this.Width = SystemMetrics.ScreenWidth;
        this.Height = SystemMetrics.ScreenHeight;
    }

    void ClockTimer_Tick(object sender, EventArgs e)
    {
        DateTime now = DateTime.Now;
        time.TextContent = now.ToString("dd/MM/yyyy HH:mm:ss");
        time.Invalidate();
    }

    public override void OnRender(DrawingContext dc)
    {
        base.OnRender(dc);
        Brush br = new SolidColorBrush(Color.Black);
       dc.DrawRectangle(br, null, 0, 0, 200, 200);
    }
}


public class Program : Microsoft.SPOT.Application
{
    public static void Main()
    {
        Program myApplication = new Program();

        Window mainWindow = myApplication.CreateWindow();

        // Start the application
        myApplication.Run(mainWindow);
    }

    private TestWindow mainWindow;

    public TestWindow CreateWindow()
    {
        // Create a window object and set its size to the
        // size of the display.
        mainWindow = new TestWindow();

        // Set the window visibility to visible.
        mainWindow.Visibility = Visibility.Visible;

        // Attach the button focus to the window.
        Buttons.Focus(mainWindow);

        return mainWindow;
    }

    private void OnButtonUp(object sender, RoutedEventArgs evt)
    {
        ButtonEventArgs e = (ButtonEventArgs)evt;

        // Print the button code to the Visual Studio output window.
        Debug.Print(e.Button.ToString());
    }
}

}

Also this app after about two/three hours shows the same behaviour:

GC: 106msec 583848 bytes used, 6755820 bytes available
Type 0F (STRING              ):    324 bytes
Type 11 (CLASS               ):   8484 bytes
Type 12 (VALUETYPE           ):    120 bytes
Type 13 (SZARRAY             ):   3360 bytes
  Type 03 (U1                  ):    252 bytes
  Type 04 (CHAR                ):    492 bytes
  Type 07 (I4                  ):     36 bytes
  Type 11 (CLASS               ):   2580 bytes
Type 15 (FREEBLOCK           ): 6755820 bytes
Type 16 (CACHEDBLOCK         ):     72 bytes
Type 17 (ASSEMBLY            ):  21960 bytes
Type 18 (WEAKCLASS           ):     96 bytes
Type 19 (REFLECTION          ):    192 bytes
Type 1B (DELEGATE_HEAD       ):    900 bytes
Type 1D (OBJECT_TO_EVENT     ):     96 bytes
Type 1E (BINARY_BLOB_HEAD    ): 543060 bytes
Type 1F (THREAD              ):    768 bytes
Type 20 (SUBTHREAD           ):     96 bytes
Type 21 (STACK_FRAME         ):   2244 bytes
Type 22 (TIMER_HEAD          ):     72 bytes
Type 27 (FINALIZER_HEAD      ):     24 bytes   
Type 31 (IO_PORT             ):     36 bytes
Type 34 (APPDOMAIN_HEAD      ):     72 bytes
Type 36 (APPDOMAIN_ASSEMBLY  ):   1872 bytes

I don’t know if it becomes unresponsive or not bacause i don’t know how to handle the lcd touch panel without GLIDE… What I see is that the time continues to increase on the screen…


#3

The data you are seeing appears after garbage collection has occurred. It is not an error indication. It is a normal occurence. If it occurs every three hours, you are managing memory very well. I doubt that there is a relationship between the appearance of this message and your program stoppage.


#4

GC runs, and something stops working - usually means that you have lost the reference to something and it’s been GC’d and can’t be called.


#5

Glide is pretty stable. I have a few devices running it for days and updating every second with no issues.

Can you show the code you are using. Post it somewhere if too large.


#6

My experience is the same as @Brett. Until I tamed the GC on my big app, I got GC messages all the time showing up in the debugger. Now I can run for at least a week or 2 (which is as long as I’ve tested) without the GC running. I definitely got burned while I was learning about the GC when the GC removed an object I needed to stick around. One of my strategies for taming the GC was to declare everything that I need to stick around as a static object.


#7

Hi everyone…
Thank you for all your suggestions… ok, ok, i have to admit… It was obviously my error…
Following your suggestions I searched in my code and…, ok, I declared the driver object as a volatile variable in the main function, so, as long as the GC did not run, everything was ok, but after my driver object was removed…
Ok, sorry for my stupid post, but thank you again to everyone, now it’s about one day that it is running smoothly…
Matteo.


#8

Not stupid post because you and others will have learned from this post. :slight_smile:


#9

Yes, I am now curious about how declaring the object volatile may have caused its removal. Seems to me that a volatile variable should be less likely to be removed since you are marking it as something the compiler needs to accept as accessed in ways not immediately obvious ( or so I thought was the purpose of the volatile keyword ). I’ve got some research to do here.

It’s quite simple in C/C++ as a keyword to cause machine instructions to always load the variable from memory before working with it, even if an “old” copy is already in a register.

C# seems to use it in a similar way… not allowing compiler optimizations to limit the loading of fresh values into the working registers.

So if an active reference exists, why would it be cleaned up with our without volatile keyword?


#10

I believe volatile is not support in MF.


#11

Hi Mike…
You are right, sorry again… I wrote “Volatile” but i meant “Local”…
I declared the display variable as a local variable inside the main function body…

Thanks,
Matteo.


#12

My understanding is any variable declared in the main function body is not subject to GC since main never goes away. If your display variable is declared inside main and is being removed by the GC, I’m confused. Maybe one of the experts could help me out of my confusion.


#13

If Main terminates, GC can happen though, right? It’s all about how you structure Main(). If you have threads and put Main to sleep (with Thread.Sleep(timeout.infinite) then you are correct, anything in Main should never go out of scope and be GCed.


#14

Hi everyone…
all you are right, the GC problem was caused by me, I declared the Display class instance inside a “InitializeTouch” function called into the main function.
In this case when the Initialize function terminates the Display variable is GCed.
Matteo.


#15

Glad you found the problem.