Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Marshal.PtrToStringAnsi() Memory Leak?

422 views
Skip to first unread message

sa...@hotmail.com

unread,
Jul 12, 2007, 5:38:58 PM7/12/07
to
I've been noticing a memory leak with the following sample code
snippet. Can someone please advise.

Have a C# Winforms app with the following code on a button-click
event.

private void button1_Click(object sender, System.EventArgs e)
{
IntPtr p1 = new IntPtr(-1);
string inputStr;
AllocString(out p1); //AllocString() called via Interop
string managedStr = Marshal.PtrToStringAnsi(p1);
Thread.Sleep(20);
Marshal.FreeHGlobal(p1);

}

The method AllocString() is defined in a C-DLL as:
CDLL_API void AllocString(char** inputStr)
{
int len = 10000000;
char * x = (char *) GlobalAlloc(0, len+1);
memset(x,65,len);
x[l]=0;
*inputStr = x;
}

On launching the application, the steady state private bytes is 10MB.

On clicking the button, I see private bytes increase by 30MB. Why the
additional overhead of 20MB for PtrToStringAnsi()? And this 20MB is
never freed. Also confirmed that the bytes allocated are in the
unmanaged code, since the .NET "# Bytes in All Heaps" never increases.

If I comment the Marshal.PtrToStringAnsi() line, private bytes always
comes back to 10MB.

Is this expected behavior for Marshal.PtrToStringAnsi() ? (.NET
Framework 1.1)

Michael Phillips, Jr.

unread,
Jul 12, 2007, 7:55:05 PM7/12/07
to
> Is this expected behavior for Marshal.PtrToStringAnsi() ? (.NET
> Framework 1.1)

It looks like the expected behavior.

Per the MSDN documentation, PtrToStringAnsi allocates a managed ANSI string
and widens it to UNICODE when it copies your unmanaged string.

Your code allocates an unmanaged string of 10,000,000 bytes which is copied
to a managed string of 20,000,000 bytes.

A managed string's memory exists until it is garbage collected.


<sa...@hotmail.com> wrote in message
news:1184276338.8...@o61g2000hsh.googlegroups.com...

sa...@hotmail.com

unread,
Jul 12, 2007, 8:33:03 PM7/12/07
to

> It looks like the expected behavior.
>
> Per the MSDN documentation, PtrToStringAnsi allocates a managed ANSI string
> and widens it to UNICODE when it copies your unmanaged string.
>
> Your code allocates an unmanaged string of 10,000,000 bytes which is copied
> to a managed string of 20,000,000 bytes.
>
> A managed string's memory exists until it is garbage collected.

Interesting. If its copying over to a "managed" string of 20MB, I
would expect the Perfmon .NET "# Bytes in All Heaps" counter to
increase by 20MB. (Since its allocating on the managed heap). But,
this counter does not change.
Instead, the "Private Bytes" counter is increasing by 20MB.

Also, tried GC.Collect but doesn't seem to drop the Private Bytes..
which seem to imply the memory is allocated on the unmanaged heap?

Willy Denoyette [MVP]

unread,
Jul 13, 2007, 8:51:54 AM7/13/07
to
<sa...@hotmail.com> wrote in message
news:1184276338.8...@o61g2000hsh.googlegroups.com...


The memory allocated by GlobalAlloc (or LocalAlloc) is not returned to the
OS after freeing, it is kept in the process space for successive use. This
memory will be reclaimed by the OS when there is memory pressure.
Note also, that your code has a *bug* in the sense that you are allocating
using "GlobalAlloc" and de-allocating using "LocalFree" (implicitely called
by FreeHGlobal). LocalFree must be paired with LocalAlloc.


0 new messages