Memory leak calling trivial ATL COM component that returns an error result

D

David Lowndes

I'm seeing a memory leak (by watching the Private Bytes for the
process in PerfMon) in this simple C# application that calls a trivial
ATL COM object method when the COM method returns an error result.

Here's the C# code (console application):

[MTAThread]
static void Main(string[] args)
{
DLTestObjLib.DLTestObj1Class dlt1 = new
DLTestObjLib.DLTestObj1Class();

for ( int indx = 0; indx < 10000000; ++indx )
{
try
{
dlt1.T2();
}
catch
{
indx = indx;
}
}
}

and the method for the ATL COM object method:

STDMETHODIMP CDLTestObj1::T2(void)
{
HRESULT hRes;
hRes = E_FAIL;
AtlReportError( CLSID_DLTestObj1, "My error message",
IID_IDLTestObj1, hRes );

return hRes;
}

If I either:

1. Change:
hRes = E_FAIL;
to
hRes = S_OK;

or:

2. Comment out the AtlReportError line

.... the memory leak disappears!

Calling the COM object from a native C++ application doesn't show a
memory leak at all.

What's giving rise to the memory leak in the C# application? Am I
missing doing something?

Dave Lowndes
 
N

Nicholas Paldino [.NET/C# MVP]

David,

I'm just guessing here, but I am thinking that the implementation of
IErrorInfo is not being released correctly. As for how to get around this,
the framework should be doing that. Have you tried calling an explicit GC
and seeing what happens (I'm thinking that it does release the managed
implementation, but doesn't decrement the reference count).

Hope this helps.
 
D

David Lowndes

I'm just guessing here, but I am thinking that the implementation of
IErrorInfo is not being released correctly. As for how to get around this,
the framework should be doing that.

Hi Nicholas,

That's the assumption I'd come to - so I'm glad you have too.
Have you tried calling an explicit GC
and seeing what happens (I'm thinking that it does release the managed
implementation, but doesn't decrement the reference count).

I've tried calling GC.Collect in the loop (if that's what you mean).
It hasn't had any effect.

Dave
 
N

Nicholas Paldino [.NET/C# MVP]

David,

Then again, is it really a bug? I mean, when you return an invalid
HRESULT, that translates to an exception thrown on the client side, which
means an object is created. Thinking about it now, this is probably why
private bytes is being incremented, IMO, not because of a memory leak.
 
D

David Lowndes

Then again, is it really a bug? I mean, when you return an invalid

What's invalid about my return value?

Actually, I think I've found the issue...

Adding tracing to my ATL module I noticed that it was being asked for
IErrorInfo and failing, so adding ISupportErrorInfo:

, public ISupportErrorInfoImpl< &IID_IDLTestObj1 >

and

COM_INTERFACE_ENTRY(ISupportErrorInfo)

appeases whatever is asking for it in the framework, and seems to
eliminate the leak.

I can't see how not implementing an interface would cause a leak - it
must surely be a bug (albeit one I can now work-around)?

Dave
 
D

David Lowndes

Unfortunately, the solution to my simple repro wasn't applicable to my
real situation (which already implemented ISupportErrorInfo), so
here's a further example which seems to accurately mirror the memory
leak I'm seeing in my real application:

static void Main(string[] args)
{
DLTestObjLib.DLTestObj1Class dlt1 = new
DLTestObjLib.DLTestObj1Class();

String [] Mods = new String[1];
Mods[0] = "World";

for ( int indx = 0; indx < 10000; ++indx )
{
try
{
dlt1.T1( "Hello", Mods );
}
catch
{
indx = indx;
}
}
}

The implementation of T1() is:

STDMETHODIMP CDLTestObj1::T1(BSTR DN, VARIANT Mods)
{
return E_FAIL;
}

and the IDL definition of T1 is:

[id(1)] HRESULT T1([in] BSTR DN, [in] VARIANT Mods);


In my real COM object, I notice that in the case when the error is
returned, the COM reference count for the passed Mods parameter (which
is really an array of other objects) keeps getting incremented. This
doesn't happen if the method returns a non-failure code, so there's
still something about the raised exception that's giving rise to this
issue.

Does anyone have any idea what in C#/CLR/Framework is giving rise to
this leak?

If anyone's interested in reproducing this problem, I can supply a
small ZIP with the sources for the 2 VS2003 test projects.

Dave Lowndes
 
D

Dave Clarke

I'm not sure if this is relevant but I found that when calling a
pooled COM+ component from c# I needed to call
Marshal.ReleaseComObject() on the object to get it to disconnect.

Dave
 
D

David Lowndes

I'm not sure if this is relevant but I found that when calling a
pooled COM+ component from c# I needed to call
Marshal.ReleaseComObject() on the object to get it to disconnect.

I don't see any relevance to my situation.

This leak only happens when the COM method returns an error result
(throws an exception in the C# code). I can only conclude this is a
bug in C# or the CLR. In the absence of any other suggestions I think
I'll have to try contacting MS PSS.

Cheers
Dave Lowndes
 
Y

Yan-Hong Huang[MSFT]

Hello Dave,

Sorry for returning here so late. We also tested it and did reproduce the
problem.

I have submitted this issue to our product group on it. Once I got any
information, I will post back here. Since you have also contacted PSS,
could you also share the feedback in the community? :)

Thanks very much.

Best regards,
Yanhong Huang
Microsoft Community Support

Get Secure! ¨C www.microsoft.com/security
This posting is provided "AS IS" with no warranties, and confers no rights.
 
D

David Lowndes

Sorry for returning here so late. We also tested it and did reproduce the

That's reassuring to know (that it's not immediately obvious that it's
my problem).
I have submitted this issue to our product group on it. Once I got any
information, I will post back here.

Thanks. I look forward to hearing how we can solve this for our
customer.
Since you have also contacted PSS,
could you also share the feedback in the community? :)

I've yet to get through the red-tape here in order to be in a position
to contact PSS (unbelievable eh). *If* I get to do so before you
reply, I'll certainly post back to this thread.

Dave
 
Y

Yan-Hong Huang[MSFT]

Hi Dave,

This may need some day, but please rest assure that I will reply here as
soon as possible. Thanks very much for your understanding.

Best regards,
Yanhong Huang
Microsoft Community Support

Get Secure! ¨C www.microsoft.com/security
This posting is provided "AS IS" with no warranties, and confers no rights.
 
R

Ravichandran J.V.

Y

Yan-Hong Huang[MSFT]

Hi David,

Currently we are working with CLR and ATL product group on it. Hopefully we
can get somebody dig into it soon. Thanks very much for your patience.

Best regards,
Yanhong Huang
Microsoft Community Support

Get Secure! ¨C www.microsoft.com/security
This posting is provided "AS IS" with no warranties, and confers no rights.
 
Y

Yan-Hong Huang[MSFT]

Hi David,

Our product group has tested it on both VS.NET and VS Whidbey. In VS
Whidbey, it has been fixed. The problem is also gone in VS.NET 2003 QFE. So
we can wait for the service pack of VS.NET 2003 to fix it. (However, since
it is not released yet. I can't make promise now. )

If there is any I can do for you, please feel free to post here. Thanks
very much.

Best regards,
Yanhong Huang
Microsoft Community Support

Get Secure! ¨C www.microsoft.com/security
This posting is provided "AS IS" with no warranties, and confers no rights.
 
D

David Lowndes

Our product group has tested it on both VS.NET and VS Whidbey. In VS
Whidbey, it has been fixed. The problem is also gone in VS.NET 2003
QFE. So we can wait for the service pack of VS.NET 2003 to fix it.
(However, since it is not released yet. I can't make promise now. )
<

Thanks for the prompt fix. I'll try to request the VS2003 QFE from my
PSS escalation so that I can verify it.

Regards
Dave Lowndes
 
Y

Yan-Hong Huang[MSFT]

Hi David,

You are welcome. :)

Thanks.

Best regards,
Yanhong Huang
Microsoft Community Support

Get Secure! ¨C www.microsoft.com/security
This posting is provided "AS IS" with no warranties, and confers no rights.
 
Y

Yan-Hong Huang[MSFT]

Thanks very much for sharing it here, Dave. :)

Best regards,
Yanhong Huang
Microsoft Community Support

Get Secure! ¨C www.microsoft.com/security
This posting is provided "AS IS" with no warranties, and confers no rights.
 
D

David Lowndes

Thanks very much for sharing it here, Dave. :)

No problem, thanks to all involved at MS for getting a prompt fix
available.

FWIW, the initial issue I noticed where a leak occurs when a COM
object sets the error using AtlReportError but doesn't support
ISupportErrorInfo appears to be resolved for .Net V2 - the March 2004
Community Preview release of VS2005 doesn't leak in this situation.

Dave
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top