470,815 Members | 1,267 Online
Bytes | Developer Community
New Post

Home Posts Topics Members FAQ

Post your question to a community of 470,815 developers. It's quick & easy.

Memory leak when using COM library

We have found a memory leak when using a COM library with a C# application.
The leak appears only if the C# application is compiled with the /optimize
flag. It goes away when the C# application is compiled with the /debug flag.
The COM library is coded to fire asynchronous events, which are handled by
the C# application. It is in the firing and handling of these events that
the leak occurs.

Why does the optimized application leak while the debug application does
not?
Is there a fix available?
Is there another way to do asynchronous event handling that will circumvent
this problem?

Attached is a small test case that recreates the problem. The only code of
real interest in the COM library is the event firing code. If the problem
that we see is in the COM library, it would have to be in this piece of code.
However, this code is more or less the output of a wizard, it is pretty
standard stuff. The C# application is also trivial, with the only item of
any real interest being the event handler. Once again, the code has been
pared down to the point of being trivial. Any insights into asynchronous
event handling through an interop assembly is appreciated.

Thanks,
Giovanni Boschi
Sonic Software Corporation
Nov 16 '05 #1
3 2367
Giovanni,

Can you post the test case?
--
- Nicholas Paldino [.NET/C# MVP]
- mv*@spam.guard.caspershouse.com

"Giovanni Boschi" <Gi************@discussions.microsoft.com> wrote in
message news:F3**********************************@microsof t.com...
We have found a memory leak when using a COM library with a C#
application.
The leak appears only if the C# application is compiled with the /optimize
flag. It goes away when the C# application is compiled with the /debug
flag.
The COM library is coded to fire asynchronous events, which are handled by
the C# application. It is in the firing and handling of these events that
the leak occurs.

Why does the optimized application leak while the debug application does
not?
Is there a fix available?
Is there another way to do asynchronous event handling that will
circumvent
this problem?

Attached is a small test case that recreates the problem. The only code
of
real interest in the COM library is the event firing code. If the problem
that we see is in the COM library, it would have to be in this piece of
code.
However, this code is more or less the output of a wizard, it is pretty
standard stuff. The C# application is also trivial, with the only item of
any real interest being the event handler. Once again, the code has been
pared down to the point of being trivial. Any insights into asynchronous
event handling through an interop assembly is appreciated.

Thanks,
Giovanni Boschi
Sonic Software Corporation

Nov 16 '05 #2
I have a simple test driver that reproduces it, but I haven't found a way to
attach files to these posts - if the full test code and library would help
and there's an email address I can send it to, let me know.

Thanks for your help,
G.

This is the C# code that appears to leak:

amespace SonicExample
{
/// <summary>
///
/// </summary>
public class MessageListener : CSLEAKTESTVS6Lib.IJMSMessageListener
{

private int msgCount = 0;

public MessageListener()
{
}
/// <summary>
/// This called by the JMSCom frame work when a mesage is received
/// </summary>
/// <param name="pJMSMessage"></param>
[MTAThread]
public void onMessage(CJMSMessage pJMSMessage)
{
System.Runtime.InteropServices.Marshal.ReleaseComO bject(pJMSMessage);
pJMSMessage = null;
GC.Collect();
++msgCount;
if ((msgCount % 1000) == 0)
Console.WriteLine ("Message {0}", msgCount);
}
}
}

This is the code, inside the COM library, that registers and fires
callbacks, respectively - this is fairly boilerplate stuff and works
correctly if the COM client is C++, or C# compiled as debug.

// register the callback
if (pListener != NULL)
{
hr = AtlAdvise (thisUnknown,
listenerUnknown,
IID_IJMSMessageListener,
&m_MessageListenerCookie);
}

// The callback routine
// messageDelivery and Fire_onMessage get called repeatedly.
int CJMSTopicSubscriber::messageDelivery()
{
IJMSMessage *jmsMessage = NULL;
HRESULT hr = S_OK;

// It has been verified that jmsMessage does not leak
jmsMessage = new CComObject<CJMSMessage>();
if (jmsMessage != NULL)
{
// If all went well return the newly created JMS COM object
jmsMessage->AddRef();
}
else
{
fprintf (stderr, _T("Failed to create JMS Message COM Object") );
return -1;
}

if (SUCCEEDED(hr))
{
hr = Fire_onMessage(jmsMessage);
if (FAILED(hr))
{
fprintf (stderr, _T("Failed to send asynch message") );
return -1;
}

jmsMessage->Release();
jmsMessage = NULL;
}
else
{
fprintf (stderr, _T("Failed to create COM message wrapper") );
return -1;
}
return 0;
}

// Fire event.
HRESULT Fire_onMessage(IJMSMessage * pMessage)
{
HRESULT ret;
T* pT = static_cast<T*>(this);
int nConnectionIndex;
int nConnections = m_vec.GetSize();

for (nConnectionIndex = 0; nConnectionIndex < nConnections;
nConnectionIndex++)
{
pT->Lock();
CComPtr<IUnknown> sp = m_vec.GetAt(nConnectionIndex);
pT->Unlock();
IJMSMessageListener* pIJMSMessageListener =
reinterpret_cast<IJMSMessageListener*>(sp.p);

if (pIJMSMessageListener != NULL)
ret = pIJMSMessageListener->onMessage(pMessage);
}

return ret;
}


"Nicholas Paldino [.NET/C# MVP]" wrote:
Giovanni,

Can you post the test case?
--
- Nicholas Paldino [.NET/C# MVP]
- mv*@spam.guard.caspershouse.com

"Giovanni Boschi" <Gi************@discussions.microsoft.com> wrote in
message news:F3**********************************@microsof t.com...
We have found a memory leak when using a COM library with a C#
application.
The leak appears only if the C# application is compiled with the /optimize
flag. It goes away when the C# application is compiled with the /debug
flag.
The COM library is coded to fire asynchronous events, which are handled by
the C# application. It is in the firing and handling of these events that
the leak occurs.

Why does the optimized application leak while the debug application does
not?
Is there a fix available?
Is there another way to do asynchronous event handling that will
circumvent
this problem?

Attached is a small test case that recreates the problem. The only code
of
real interest in the COM library is the event firing code. If the problem
that we see is in the COM library, it would have to be in this piece of
code.
However, this code is more or less the output of a wizard, it is pretty
standard stuff. The C# application is also trivial, with the only item of
any real interest being the event handler. Once again, the code has been
pared down to the point of being trivial. Any insights into asynchronous
event handling through an interop assembly is appreciated.

Thanks,
Giovanni Boschi
Sonic Software Corporation


Nov 16 '05 #3
Is this the whole C# program?
[MTAThread]
public void onMessage(CJMSMessage pJMSMessage)
The MTAThread attribute can only be applied to the Main entry of an
executable program.

Please post complete samples that can be compiled and that illustrate the
problem.
Also give us some more details on how you define a leak, what tools have you
used and what kind of memory are you talking about.

Willy.

"Giovanni Boschi" <Gi************@discussions.microsoft.com> wrote in
message news:06**********************************@microsof t.com...I have a simple test driver that reproduces it, but I haven't found a way
to
attach files to these posts - if the full test code and library would help
and there's an email address I can send it to, let me know.

Thanks for your help,
G.

This is the C# code that appears to leak:

amespace SonicExample
{
/// <summary>
///
/// </summary>
public class MessageListener : CSLEAKTESTVS6Lib.IJMSMessageListener
{

private int msgCount = 0;

public MessageListener()
{
}
/// <summary>
/// This called by the JMSCom frame work when a mesage is received
/// </summary>
/// <param name="pJMSMessage"></param>
[MTAThread]
public void onMessage(CJMSMessage pJMSMessage)
{
System.Runtime.InteropServices.Marshal.ReleaseComO bject(pJMSMessage);
pJMSMessage = null;
GC.Collect();
++msgCount;
if ((msgCount % 1000) == 0)
Console.WriteLine ("Message {0}", msgCount);
}
}
}

This is the code, inside the COM library, that registers and fires
callbacks, respectively - this is fairly boilerplate stuff and works
correctly if the COM client is C++, or C# compiled as debug.

// register the callback
if (pListener != NULL)
{
hr = AtlAdvise (thisUnknown,
listenerUnknown,
IID_IJMSMessageListener,
&m_MessageListenerCookie);
}

// The callback routine
// messageDelivery and Fire_onMessage get called repeatedly.
int CJMSTopicSubscriber::messageDelivery()
{
IJMSMessage *jmsMessage = NULL;
HRESULT hr = S_OK;

// It has been verified that jmsMessage does not leak
jmsMessage = new CComObject<CJMSMessage>();
if (jmsMessage != NULL)
{
// If all went well return the newly created JMS COM object
jmsMessage->AddRef();
}
else
{
fprintf (stderr, _T("Failed to create JMS Message COM Object") );
return -1;
}

if (SUCCEEDED(hr))
{
hr = Fire_onMessage(jmsMessage);
if (FAILED(hr))
{
fprintf (stderr, _T("Failed to send asynch message") );
return -1;
}

jmsMessage->Release();
jmsMessage = NULL;
}
else
{
fprintf (stderr, _T("Failed to create COM message wrapper") );
return -1;
}
return 0;
}

// Fire event.
HRESULT Fire_onMessage(IJMSMessage * pMessage)
{
HRESULT ret;
T* pT = static_cast<T*>(this);
int nConnectionIndex;
int nConnections = m_vec.GetSize();

for (nConnectionIndex = 0; nConnectionIndex < nConnections;
nConnectionIndex++)
{
pT->Lock();
CComPtr<IUnknown> sp = m_vec.GetAt(nConnectionIndex);
pT->Unlock();
IJMSMessageListener* pIJMSMessageListener =
reinterpret_cast<IJMSMessageListener*>(sp.p);

if (pIJMSMessageListener != NULL)
ret = pIJMSMessageListener->onMessage(pMessage);
}

return ret;
}


"Nicholas Paldino [.NET/C# MVP]" wrote:
Giovanni,

Can you post the test case?
--
- Nicholas Paldino [.NET/C# MVP]
- mv*@spam.guard.caspershouse.com

"Giovanni Boschi" <Gi************@discussions.microsoft.com> wrote in
message news:F3**********************************@microsof t.com...
> We have found a memory leak when using a COM library with a C#
> application.
> The leak appears only if the C# application is compiled with the
> /optimize
> flag. It goes away when the C# application is compiled with the /debug
> flag.
> The COM library is coded to fire asynchronous events, which are handled
> by
> the C# application. It is in the firing and handling of these events
> that
> the leak occurs.
>
> Why does the optimized application leak while the debug application
> does
> not?
> Is there a fix available?
> Is there another way to do asynchronous event handling that will
> circumvent
> this problem?
>
> Attached is a small test case that recreates the problem. The only
> code
> of
> real interest in the COM library is the event firing code. If the
> problem
> that we see is in the COM library, it would have to be in this piece of
> code.
> However, this code is more or less the output of a wizard, it is pretty
> standard stuff. The C# application is also trivial, with the only item
> of
> any real interest being the event handler. Once again, the code has
> been
> pared down to the point of being trivial. Any insights into
> asynchronous
> event handling through an interop assembly is appreciated.
>
> Thanks,
> Giovanni Boschi
> Sonic Software Corporation


Nov 16 '05 #4

This discussion thread is closed

Replies have been disabled for this discussion.

Similar topics

4 posts views Thread by Morten Aune Lyrstad | last post: by
10 posts views Thread by eyh5 | last post: by
23 posts views Thread by James | last post: by
4 posts views Thread by mast2as | last post: by
8 posts views Thread by vidya.bhagwath | last post: by
7 posts views Thread by Ragnar Agustsson | last post: by
reply views Thread by mihailmihai484 | last post: by
By using this site, you agree to our Privacy Policy and Terms of Use.