Ref count problem when using managed extensions

B

Ben Terry

I have imported a legacy C++ project into a VisualStudio.NET 2003 solution.
I have some new C# projects in the solution as well. I am using the managed
extensions in my C++ project so that I can use the managed C# objects within
my C++ project. Here's the problem: I am getting a debug assertion in
cmdtarg.cpp (line 48) of my main CWinApp derived class when I exit the
application:

CCmdTarget::~CCmdTarget()
{
....
ASSERT(m_dwRef <= 1); // <<<< Line 48 where I am getting the assertion.
....
}

The strange thing is that I only get this assertion if I have created a
managed gcroot<> object within the main CWinApp derived class. Why does
creating a managed object increase the ref count on CWinApp? That seems
very odd. Here is how I am creating the managed object within CWinApp:

In the header:
#using <mscorlib.dll>
#using <system.dll>
#using <system.windows.forms.dll>
#using "PetToolTCPLib.dll" // Library of my C# managed classes
using namespace PetToolTCPLib;
using namespace System;

In the .cpp:
#pragma push_macro("new")
#undef new
m_pTCPTool = new CToolMain();
#pragma pop_macro("new")

m_pTCPTool->Show();

In the destructor of the .cpp:
m_pTCPTool->Close();
m_pTCPTool->Dispose();
m_pTCPTool = NULL;

Once again, my question is: Why does creating a managed object increase the
ref count on CWinApp?
How do I resolve this problem?

Ben
 
B

Ben Terry

I solved the problem. I was not properly "disposing" my gcroot object.
Doing so now enables the CWinApp ref count to decrement and shutdown without
the assertion. I'm still not sure why that refcount is affected by my
gcroot object.
 
B

Ben Terry

Scratch that...still haven't solved the problem. Anyone have any ideas
about this one?
 
E

Eckhard Schwabe

Hello Ben,

Ben said:
I am using the
managed

I had the same problem. This seems to be a known issue with the currnet
version of .Net.
Leo Chen from Microsoft posted a message to
microsoft.public.dotnet.languages.csharp
Currently, we can work around this problem using following methods:

1. Handle the CWinApp::ExitInstance. Use code similar to the following
to
release the additional reference to the message filter.

#include <afxole.h>

BOOL CMFCDlgApp::ExitInstance()
{
COleMessageFilter* pFilter = AfxOleGetMessageFilter();
ULONG lCount = pFilter->m_xMessageFilter.Release();
if(lCount<=1)
pFilter->m_xMessageFilter.AddRef();
return CWinApp::ExitInstance();
}
2. Another method can be applied on the C# side. We can call GC.Collect >to
collect the object references after the form is closed:

public bool ShowDbx()
{DTest1 dlg1 = new DTest1();
dlg1.ShowDialog();
dlg1.Close();
dlg1.Dispose();

GC.Collect();

return true;
}

I first tried the solution number one, but then realized I would have to
call GC.Collect() after every MessageBox::Show, which somehow didn't
look very promising to me.

So I chose the 2nd solution which seems to work just fine.

Hope that helps,

Ecki
 

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