Home | Contact Us | FAQ | Search & Site Map | Link to Us
Sign In | Join | Other 45 Sites in Network
HomeAnnouncementsFree MagazinesWhite PapersSubmit Content
Discussion GroupsASP.NETWindows FormsLanguages.NET FrameworkVisual Studio.NET
Articles.NET FrameworkASP.NETToolsWindows Forms
.NET DirectoryOpen Source ProjectsUser GroupsWeb Resources
Related Topics
Visual Basic 6SQL ServerMS AccessOther DB ProductsMS Server ProductsMore Topics ...

.NET Forum / .NET Framework / Interop / April 2005

Tip: Looking for answers? Try searching our database.

Stack Memory Leak in C#

Thread view: 
Enable EMail Alerts  Start New Thread
Thread rating: 
Robert Bouillon - 26 Apr 2005 17:08 GMT
I've got a memory leak problem with my Stack in a class I created for Serial
Port Communication.

I've narrowed it doen to a subclass I created to monitor the Win32 events
fired for the Serial Port (Using WaitCommEvent).

The "Status" subclass allocates unmanaged memory for the Event Handle and
Overlapped struct in the ctor and frees the memory in the
(IDisposable).Dispose method for the object. An infinite loop checks the
event / status on a background thread. No memory is allocated explicitly in
this loop, however I'm definately leaking my stack memory from within this
loop.

This leads me to believe it's a problem with my P/Invoke declarations. The
only thing I do differently than most other P/Invoke statements I've seen is
rather than using "out uint" for event masks, I'm using "out MyEnum". I
think this is where my problem lies, however it takes me almost an hour to
reproduce this error so I'm having some difficulty narrowing it down.

<code>
   [Flags]
   private enum ModemStatus : uint
   {
     MS_CTS_ON = 0x0010,
     MS_DSR_ON = 0x0020,
     MS_RING_ON = 0x0040,
     MS_RLSD_ON = 0x0080
   }

   [DllImport("kernel32.dll")]
   private static extern bool GetCommModemStatus(IntPtr hFile, out
ModemStatus lpModemStat);
</code>

Do I have to clean lpModemStat explicitly?
Is this possibly a problem with P/Invoke?
How can I explicitly free lpModemStat for testing?
Is there a way for me to watch my stack allocation at runtime?

Thanks in Advance

(P.S. Sorry for the duplicate post. This was originally posted in
microsoft.public.dotnet.framework until I realized that it's likely an
interop issue)
Gabriel Lozano-Morán - 26 Apr 2005 18:49 GMT
>    [DllImport("kernel32.dll")]
>    private static extern bool GetCommModemStatus(IntPtr hFile, out
> ModemStatus lpModemStat);

What happens if for example the CTS signal and ring indicator signal are
both on?

...
[DllImport("kernel32.dll")]
private static extern Boolean GetCommModemStatus(IntPtr hFile, out uint
lpModemStat);
...
if(GetCommModemStatus(handle, out modemStatus) == true)
{
   bool MS_CTS = ((modemStatus & (uint)ModemStatus.MS_CTS_ON) != 0);
   bool MS_DSR = ((modemStatus & (uint)ModemStatus.MS_DSR_ON) != 0);
   bool MS_RING = ((modemStatus & (uint)ModemStatus.MS_RING_ON) != 0);
   bool MS_RLSD = ((modemStatus & (uint)ModemStatus.MS_RLSD_ON) != 0);
}

Gabriel Lozano-Morán
Robert Bouillon - 26 Apr 2005 20:00 GMT
The FLAGS attrbute allows the ToString to display all applicable flags as
they relate to the enumerated value:

==========================
[Command Window]
> lpModemStat.ToString()
> "MS_CTS_ON,MS_RING_ON"
==========================

The actual code method is:

==========================
     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");

       if(((ms&ModemStatus.MS_CTS_ON)!=0)!=p_CTS)
         p_CTS = !p_CTS;

       if(((ms&ModemStatus.MS_DSR_ON)!=0)!=p_DSR)
         p_DSR = !p_DSR;

       if(((ms&ModemStatus.MS_RING_ON)!=0)!=p_Ring)
         p_Ring = !p_Ring;

       if(((ms&ModemStatus.MS_RLSD_ON)!=0)!=p_RLSD)
         p_RLSD = !p_RLSD;
     }
===========================

Object events are fired as a direct result of an EV_* flag in the calling
method. This method only serves to update line status.

I've found it to make my code a lot cleaner, as long as it's not the cause
of this Memory Leak.

Any ideas on what may be causing this?

--ROBERT

> >    [DllImport("kernel32.dll")]
> >    private static extern bool GetCommModemStatus(IntPtr hFile, out
[quoted text clipped - 17 lines]
>
> Gabriel Lozano-Morán
Gabriel Lozano-Morán - 26 Apr 2005 20:18 GMT
I am just wondering what would open if an error occured in the
GetCommModemStatus function and the out parameter doesn't get set or what
value is given to the out parameter when an error occurs? Also have you
tried using a ref parameter instead?

Gabriel Lozano-Morán

> The FLAGS attrbute allows the ToString to display all applicable flags as
> they relate to the enumerated value:
[quoted text clipped - 62 lines]
>>
>> Gabriel Lozano-Morán
Robert Bouillon - 26 Apr 2005 20:59 GMT
As far as I know, the value is set to 0 on error.

It's worth a shot. It's just difficult, as it takes me about an hour to
reproduce this error.

--ROBERT
> I am just wondering what would open if an error occured in the
> GetCommModemStatus function and the out parameter doesn't get set or what
[quoted text clipped - 69 lines]
> >>
> >> Gabriel Lozano-Morán
Robert Bouillon - 27 Apr 2005 13:24 GMT
The problem was actually a bad ReadFile / WriteFile P/Invoke declaration.

   private static extern bool WriteFile(IntPtr fFile, Byte[] lpBuffer,
     UInt32 nNumberOfBytesToWrite, out UInt32 lpNumberOfBytesWritten,
IntPtr lpOverlapped);

   private static extern bool ReadFile(IntPtr hFile, [Out] Byte[] lpBuffer,
UInt32 nNumberOfBytesToRead,
     out UInt32 nNumberOfBytesRead, IntPtr lpOverlapped);

was changed to:

   static extern bool WriteFile(IntPtr hFile, byte [] lpBuffer,uint
nNumberOfBytesToWrite, out uint lpNumberOfBytesWritten,
     [In] ref System.Threading.NativeOverlapped lpOverlapped);

   public static extern bool ReadFile(IntPtr hFile, [Out] byte[] lpBuffer,
uint nNumberOfBytesToRead,
     out uint lpNumberOfBytesRead, [In] ref
System.Threading.NativeOverlapped lpOverlapped);

Despite the fact that "Overlapped" is a struct, the P/Invoke prevented the
data from being freed when the variable fell out of scope.

Maybe this will help someone in the future. Thanks to everyone who posted.

--ROBERT

> As far as I know, the value is set to 0 on error.
>
[quoted text clipped - 79 lines]
> > >>
> > >> Gabriel Lozano-Morán

Free Magazines

Get these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...

Oracle MagazineNetwork ComputingComputer WorldBio-IT WorldeWeekInformation WeekInfosecurity
 
Sign In
Join
My Latest Posts
My Monitored Threads
My Blog
My Photo Gallery
My Profile
My Homepage

Start New Thread
Enable EMail Alerts
Rate this Thread



©2008 Advenet LLC   Privacy Policy - Terms of Use
This website includes both content owned or controlled by Advenet as well as content owned or controlled by third parties.