What is "Out of Memory" when I have lots?

VS.NET 2003

I have a OwnerDrawFixed ComboBox.  Sometimes, only sometimes but too frequently, when I click or is scrolling through the list (5 items) I get an Out of Memory exception in the DrawItem event handler at the point where I was drawing a dashed line (my drop down list is a list of dash styles).  The exact error is "'System.OutOfMemoryException' occurred in system.drawing.dll"

I have plenty of memory.  A cursory check with Task Manager shows that it is using only low tens of MB.  I put a Debug.WriteLine statement in the event handler, and the handler is called only a few times before it crashes.  What information can I output in the Debug statement to try and trace the source of the error

What does Out of Memory really mean when there is plenty of memory   Are there any caveats to watch out when doing DrawItem   I searched and found only one unanswered question at here: http://www.codeproject.com/vb/net/VbNetOwnerDrawMenu.asp msg=869630#xxxx.

Thanks for any help.

 



Answer this question

What is "Out of Memory" when I have lots?

  • Lars Larsson

    Thanks for the fast and good reply!

    I don't see any strange thing, only you don't dispose you pen. But that shouldn't be the bottleneck, but you can give it a try:


    private void TodayStyle_DrawItem(object sender, DrawItemEventArgs e)
    {
    if( e.Index < 0 || e.Index > 4 )
    {
    return;
    }

    e.DrawBackground();

    Rectangle r = e.Bounds;

    using(Pen pen = new Pen( TodayColor.BackColor,TodayThickness.SelectedIndex + 1 ) )
    {
    pen.DashStyle=(DashStyle)e.Index+1; //going for enum values of 1-5

    Point beginPoint = new Point( 0, r.Top + r.Height / 2 );
    Point endPoint = new Point( r.Right, r.Top + r.Height / 2 );
    e.Graphics.DrawLine( pen, beginPoint, endPoint );
    }

    if ( (e.State & DrawItemState.Focus) != 0 )
    {
    e.DrawFocusRectangle();
    }
    }




  • The Doc

    PJ, thanks for all your help.  I think (I hope) I have found the problem.

    The DashStyle Eumeration members are Custom, Dash, DashDot, DashDotDot, Dot and Solid.  I mistook them to be 0 to 5 in that order.  But that was in alphabetical order. 

    0 to 5 are actually Solid, Dash, Dot, DashDot, DashDotDot and Custom.

    I wanted to avoid Custom.  The problem occurs only during when the ComboBox SelectedIndex of 4 (meaning 5), Custom, is painted.  And I didn't define what Custom is.

    Thanks.

    PS: A separate question would be how to use enumerated values and be future proof


  • FlintZA

    Thanks for the fast response.

    My Code:



    private void TodayStyle_DrawItem(object sender, System.Windows.Forms.DrawItemEventArgs e)
    {
    Debug.WriteLine("DrawItem "+e.Index+" state: "+e.State.ToString()+" Color: "+e.BackColor.Name+" "+e.Bounds.ToString());
    if (e.Index<0 || e.Index>4) return;
    e.DrawBackground();
    Rectangle r = e.Bounds;
    Pen pen =
    new Pen(TodayColor.BackColor,TodayThickness.SelectedIndex+1);
    pen.DashStyle=(DashStyle)e.Index+1;  //going for enum values of 1-5
    e.Graphics.DrawLine(pen,0,r.Top+r.Height/2,r.Right,r.Top+r.Height/2);

    if ((e.State & DrawItemState.Focus)!=0) e.DrawFocusRectangle();
    }

     

    ---Output when I just clicked the combo once and the drop down list opens (third item was selected at start).  Doesn't look like an endless loop situation:

    DrawItem 2 state: ComboBoxEdit Color: Window {X=3,Y=3,Width=94,Height=15}
    DrawItem 2 state: Selected, Focus, ComboBoxEdit Color: Highlight {X=3,Y=3,Width=94,Height=15}
    DrawItem 2 state: ComboBoxEdit Color: Window {X=3,Y=3,Width=94,Height=15}
    DrawItem 2 state: ComboBoxEdit Color: Window {X=3,Y=3,Width=94,Height=15}
    DrawItem 2 state: Selected Color: Highlight {X=0,Y=30,Width=114,Height=15}
    DrawItem 0 state: None Color: Window {X=0,Y=0,Width=114,Height=15}
    DrawItem 1 state: None Color: Window {X=0,Y=15,Width=114,Height=15}
    DrawItem 2 state: Selected Color: Highlight {X=0,Y=30,Width=114,Height=15}
    DrawItem 3 state: None Color: Window {X=0,Y=45,Width=114,Height=15}
    DrawItem 4 state: None Color: Window {X=0,Y=60,Width=114,Height=15}

    An unhandled exception of type 'System.OutOfMemoryException' occurred in system.drawing.dll

    Additional information: Out of memory.

    ------Stack trace:

    I have global replaced system.windows.forms to S.W.F for brevity.

     system.drawing.dll!System.Drawing.Graphics.CheckErrorStatus(int status = 3) + 0x41 bytes
     system.drawing.dll!System.Drawing.Graphics.DrawLine(System.Drawing.Pen pen = {Color={RGB=0xff004040}}, int x1 = 0, int y1 = 67, int x2 = 114, int y2 = 67) + 0xc2 bytes
    >My Prog.exe!MyProg.TodayMarker.TodayStyle_DrawItem(System.Object sender = {S.W.F.ComboBox}, S.W.F.DrawItemEventArgs e = {S.W.F.DrawItemEventArgs}) + 0x312 bytesC#
     S.W.F.dll!S.W.F.ComboBox.OnDrawItem(S.W.F.DrawItemEventArgs e = {S.W.F.DrawItemEventArgs}) + 0x4c bytes
     S.W.F.dll!S.W.F.ComboBox.WmReflectDrawItem(S.W.F.Message m = {S.W.F.Message}) + 0x165 bytes
     S.W.F.dll!S.W.F.ComboBox.WndProc(S.W.F.Message m = {S.W.F.Message}) + 0x28b bytes
     S.W.F.dll!ControlNativeWindow.OnMessage(S.W.F.Message m = {S.W.F.Message}) + 0x13 bytes
     S.W.F.dll!ControlNativeWindow.WndProc(S.W.F.Message m = {S.W.F.Message}) + 0xda bytes
     S.W.F.dll!S.W.F.NativeWindow.DebuggableCallback(int hWnd = 14486086, int msg = 8235, int wparam = 14486086, int lparam = 1239140) + 0x3d bytes
     S.W.F.dll!S.W.F.Control.SendMessage(int msg = 8235, int wparam = 14486086, int lparam = 1239140) + 0x48 bytes
     

    .... stuff deleted on Mar 31 after problem was solved

    dwComponentID = 172, int reason = -1, int pvLoopData = 0) + 0x349 bytes
     S.W.F.dll!ThreadContext.RunMessageLoopInner(int reason = -1, S.W.F.ApplicationContext context = {S.W.F.ApplicationContext}) + 0x1f5 bytes
     S.W.F.dll!ThreadContext.RunMessageLoop(int reason = -1, S.W.F.ApplicationContext context = {S.W.F.ApplicationContext}) + 0x50 bytes
     S.W.F.dll!S.W.F.Application.Run(S.W.F.Form mainForm = {MyProg.Form1}) + 0x34 bytes
     My Prog.exe!MyProg.Form1.Main() + 0x20 bytesC#

    --

    I am developing on a Windows Server 2003 PC.  Error occurs both in IDE and standalone exe.  When I run the exe on an XP machine, I have not managed to generate the error.

    Thanks for your help


  • Bader Cheema

    Aha, but that would not be very friendly in non-English using countries. Also I wonder if it would survive obsfuscating through renaming (eg the Dotfuscator Community Edition). I once used ToString() instead of GetNames and it was all the renamed values that were returned.
  • AlG

    A OutOfMemoryException normally occurds normally when there is not enough memory to continue the execution.

    This can also be the stack that can be full very quickly when a get property that refers to itself or a endless loop that builds a buffer and more then thousand other scenarios.

    Can you post relevant code Does it allways happen on the same statement Can you post the stack-trace


  • Donald Burr

    The you can just add a helper class:


    public class ValueHelper
    {
    private string _text;
    private DashStyle _value;

    public string Text
    {
    get
    {
    return _text;
    }
    set
    {
    _text = value;
    }
    }

    public DashStyle Value
    {
    get
    {
    return value;
    }
    set
    {
    _value = value;
    }
    }

    public ValueHelper()
    {
    // Nothing todo.
    }

    public ValueHelper( string text, DashStyle value )
    {
    _text = text;
    _value = value;
    }

    public override string ToString()
    {
    if( Text != null )
    {
    return Text;
    }
    else
    {
    return string.Empty;
    }
    }
    }



    Create the needed instances and add them to the combobox. If you need the selected value, just cast the SelectedItem property of the combobox to an ValueHelper object and read the value.


  • mufasa

    K. Kong, you can add the Name values of the Enum to the combobox and later parse the selected Name value back to the enum value:

    Add names value

    String[] names = Enum.GetNames( typeof(DashStyle) );
    comboBox.Items.AddRange( names );



    Get selected style

    String name = (String)comboBox.SelectedItem;
    DashStyle style = (DashStyle)Enum.Parse( typeof(DashStyle), name, true );




  • What is "Out of Memory" when I have lots?