Re: StackOverflowException.



Willy,

Thanks for the reply :)

My call stack is only 27 calls deep: 17 of them are Windows Forms calls (via
"Show non-user code"). I checked all of my threads as well and they're all
behaving normally. To-date, on StackOverflows caused by recursion, I've
always gotten an exception. I've tried to reproduce this error 3 times, and
only once did I get this exception. The other 2 times I got obscure errors
and was unable to view my local variables, leading me to believe that lack
of stack space caused my VM to go screwy.

I narrowed it down to what I believe may be the culprit. I recently added a
"Status" subclass to my Rs232Stream class. The Status object monitors the
Serial Port in an infinite loop, on background thread, making calls to
win32. Disabling this thread alleviates the problem.

Here's a snippet (C#):

=====================================
/// <summary>
/// Monitors the Serial Port opened by the parent stream for events
/// </summary>
/// <remarks>
/// Sits directly on the m_StatusThread
/// <see cref="Parent"/>
/// <see cref="m_StatusThread"/>
/// </remarks>
private void Monitor()
{
InitEventMask();

while(true)
{
if(!WaitCommEvent(p_Parent.hPort, m_UnmanagedCurrentEvent,
m_UnmanagedOverlappedHandle))
{
NativeError err = Win32Exception.Check(false);
if (err!= NativeError.ERROR_IO_PENDING)
throw new IOException("Error setting comm event handle", new
Win32Exception());
}

m_StatusChangeEvent.WaitOne();
Requery(p_Parent.hPort);
}
}

public Rs232Status(Rs232Stream parent)
{
p_Parent = parent;

Overlapped wo = new Overlapped();
wo.hEvent = m_StatusChangeEvent.Handle;

m_UnmanagedOverlappedHandle =
Marshal.AllocHGlobal(Marshal.SizeOf(wo));
Marshal.StructureToPtr(wo, m_UnmanagedOverlappedHandle, true);

m_UnmanagedCurrentEvent =
Marshal.AllocHGlobal(Marshal.SizeOf(Type.GetType("System.UInt32")));
Marshal.WriteInt32(m_UnmanagedCurrentEvent,0);
}

/// <summary>
/// Checks the status of the Flow Control Lines
/// </summary>
/// <param name="portHandle">Handle to the opened port</param>
/// <remarks>Called by Requery</remarks>
public void UpdateLines()
{
ModemStatus ms;
while(!GetCommModemStatus(p_Parent.hPort,out ms))
if(Win32Exception.Check(false)==NativeError.ERROR_IO_PENDING)
continue;
else
throw new Win32Exception("Error during GetCommModemStatus");
{...} //---> Event Calls and Field Updates
}
===============================
InitEventMask encapsulates the Win32 SetCommMask call. Requery is a lot of
bloated code that checks the Event Flags and calls some OnXXXX methods to
fire events and update some local fields.

It's pretty cut-and-dry. It's an infinite loop that makes a few minor calls
to unmanaged IO code. No unmanaged memory is allocated outside of the ctor,
so I'm really at a total loss as to where I'm leaking stack memory.

I don't mind posting the entire status class here, but I know how painful
that is so I'm going to just post the calls I make to unmanaged code or the
marshaller. Perhaps you'll see a function that manipulates memory or catch
something I'm missing?

[DllImport("kernel32.dll")]
EscapeCommFunction
ClearCommError
GetOverlappedResult
WaitCommEvent
SetCommMask
GetCommModemStatus

[.NET Interop]
Marshal.ReadInt32
Marshal.StructureToPtr

Here's an idea: My EscapeCommFunction has the following declaration:
[DllImport("kernel32.dll")]
private static extern bool EscapeCommFunction(IntPtr hFile, CommFunction
dwFunc);

CommFunction is a private managed struct I use in the class. I prefer to let
..NET interop marshal my variables for me to save time / code. Is it possible
that in this scenario, the dwFunc is never being destroyed? I'm not
destroying it explicitly.

Thanks.
--ROBERT

P.S. Good to know about arrays. I could have sworn I read something that
said blittable-typed arrays were stored on the stack. At least that gives
stackalloc a little more prominence :) I wish there was a way that
strong-typed streams could access stackalloc arrays, but we all know the
rules about pointers in the CLR :-/


.



Relevant Pages

  • memory leak in (?)... (redux)
    ... the mem leaks in our long-running tcl daemons. ... when actively exercised the app grows continuously. ... the mystery is that while our audit code does show us a couple of arrays ... and memory are checked and meanwhile externally, ...
    (comp.lang.tcl)
  • Re: Strategy for caches & GC
    ... I end up writing manual allocators for byte arrays. ... memory to insure it sits in the LOH and suballocate from there (ala ... ArraySlicehandle to work with buffers. ... and manual management for memory and GC generation 0 for efficient ...
    (microsoft.public.dotnet.framework.clr)
  • Re: perl eating up memory slowly until program stops - any ideas ?
    ... Arrays are created, variables are set, ... For lexical scoping, a single chunk of memory, reserved by ... Private blocks, you have discussed this a number of times ...
    (comp.lang.perl.misc)
  • Re: How: multiple program instances sharing same data
    ... so this memory isn't shared. ... private copy of JITted code. ... Ok, because the .exe isn't native to my machine, it gets just-in-time ... I am talking about a Windows NET App, ...
    (microsoft.public.dotnet.languages.csharp)
  • Re: How can I tell the application total memory usage? (LONG!)
    ... No you can't simply add these two to calculate the amount of memory your ... of memory taken by a process using the performance counters but you can get ... The "Private bytes" represents the total of the pages, ... So while might be important to keep an eye at your memory consumption, ...
    (microsoft.public.dotnet.languages.csharp)