Memory leak in interop

T

Trokey

I am making interop calls to an object in a .NET component from a C++
program and am leaking memory... the following is some sample code:

////////////////////////////////////////
// .NET component (Test)
////////////////////////////////////////

// interface
[InterfaceType(ComInterfaceType.InterfaceIsDual)]
[Guid("D3DF5658-3D3F-436b-B6A6-F10E77AE3F5F")]
public interface IDotNetInterface
{
int getString(string aParam1, string aParam2, out string aValue);
}

// class
[ClassInterface(ClassInterfaceType.None)]
[ProgId("Test.DotNetInterface")]
public class DotNetInterface : IDotNetInterface
{
public int getString(string aParam1, string aParam2, out string aValue)
{
aValue = "some text";
GC.Collect();
return 1;
}
}

///////////////////////////////////
// C++ program
///////////////////////////////////

#import "Test.tlb" no_namespace named_guids

int _tmain(int argc, _TCHAR* argv[])
{
CoInitializeEx(NULL, COINIT_MULTITHREADED);

IDotNetInterfacePtr pPtr = IDotNetInterface(__uuidof(DotNetInterface));
pPtr->AddRef();

_bstr_t lParam1 = "1";
_bstr_t lParam2 = "2";

BSTR lValue;
int lResult = pPtr->getString(lParam1, lParam2, &lValue); // <-- LEAK!!

pPtr->Release();
pPtr = NULL;
}


I've tried all sorts of things (trying to explicitly release the BSTR
memory, etc.), but no effect. What is causing this leak, and how do I solve
it???

Thanks in advance,
Matt
 
N

Nicholas Paldino [.NET/C# MVP]

Trokey,

I don't see how the runtime is causing the leak. If anything, you need
to call SysFreeString to free the string.

You can also use a CComBSTR class and it will handle this automatically.

Also, you don't need to call the static Collect method on the GC class.

What do you have to support that there is a leak?
 
S

SCG

If anything, you need to call SysFreeString to free the string.

Absolutely. I believe this may be your issue.


Nicholas Paldino said:
Trokey,

I don't see how the runtime is causing the leak. If anything, you need
to call SysFreeString to free the string.

You can also use a CComBSTR class and it will handle this automatically.

Also, you don't need to call the static Collect method on the GC class.

What do you have to support that there is a leak?


--
- Nicholas Paldino [.NET/C# MVP]
- (e-mail address removed)

Trokey said:
I am making interop calls to an object in a .NET component from a C++
program and am leaking memory... the following is some sample code:

////////////////////////////////////////
// .NET component (Test)
////////////////////////////////////////

// interface
[InterfaceType(ComInterfaceType.InterfaceIsDual)]
[Guid("D3DF5658-3D3F-436b-B6A6-F10E77AE3F5F")]
public interface IDotNetInterface
{
int getString(string aParam1, string aParam2, out string aValue);
}

// class
[ClassInterface(ClassInterfaceType.None)]
[ProgId("Test.DotNetInterface")]
public class DotNetInterface : IDotNetInterface
{
public int getString(string aParam1, string aParam2, out string aValue)
{
aValue = "some text";
GC.Collect();
return 1;
}
}

///////////////////////////////////
// C++ program
///////////////////////////////////

#import "Test.tlb" no_namespace named_guids

int _tmain(int argc, _TCHAR* argv[])
{
CoInitializeEx(NULL, COINIT_MULTITHREADED);

IDotNetInterfacePtr pPtr = IDotNetInterface(__uuidof(DotNetInterface));
pPtr->AddRef();

_bstr_t lParam1 = "1";
_bstr_t lParam2 = "2";

BSTR lValue;
int lResult = pPtr->getString(lParam1, lParam2, &lValue); // <-- LEAK!!

pPtr->Release();
pPtr = NULL;
}


I've tried all sorts of things (trying to explicitly release the BSTR
memory, etc.), but no effect. What is causing this leak, and how do I solve
it???

Thanks in advance,
Matt
 
T

Trokey

I've tried all these things, but no difference... I know there is a leak
because I monitor the private bytes in perfmon and the memory allocated by
the getString call is never released.

Matt

Nicholas Paldino said:
Trokey,

I don't see how the runtime is causing the leak. If anything, you need
to call SysFreeString to free the string.

You can also use a CComBSTR class and it will handle this automatically.

Also, you don't need to call the static Collect method on the GC class.

What do you have to support that there is a leak?


--
- Nicholas Paldino [.NET/C# MVP]
- (e-mail address removed)

Trokey said:
I am making interop calls to an object in a .NET component from a C++
program and am leaking memory... the following is some sample code:

////////////////////////////////////////
// .NET component (Test)
////////////////////////////////////////

// interface
[InterfaceType(ComInterfaceType.InterfaceIsDual)]
[Guid("D3DF5658-3D3F-436b-B6A6-F10E77AE3F5F")]
public interface IDotNetInterface
{
int getString(string aParam1, string aParam2, out string aValue);
}

// class
[ClassInterface(ClassInterfaceType.None)]
[ProgId("Test.DotNetInterface")]
public class DotNetInterface : IDotNetInterface
{
public int getString(string aParam1, string aParam2, out string aValue)
{
aValue = "some text";
GC.Collect();
return 1;
}
}

///////////////////////////////////
// C++ program
///////////////////////////////////

#import "Test.tlb" no_namespace named_guids

int _tmain(int argc, _TCHAR* argv[])
{
CoInitializeEx(NULL, COINIT_MULTITHREADED);

IDotNetInterfacePtr pPtr = IDotNetInterface(__uuidof(DotNetInterface));
pPtr->AddRef();

_bstr_t lParam1 = "1";
_bstr_t lParam2 = "2";

BSTR lValue;
int lResult = pPtr->getString(lParam1, lParam2, &lValue); // <-- LEAK!!

pPtr->Release();
pPtr = NULL;
}


I've tried all sorts of things (trying to explicitly release the BSTR
memory, etc.), but no effect. What is causing this leak, and how do I solve
it???

Thanks in advance,
Matt
 
W

Willy Denoyette [MVP]

int _tmain(int argc, _TCHAR* argv[])
{
CoInitialize(NULL);
IDotNetInterfacePtr pPtr(__uuidof(DotNetInterface));
_bstr_t lParam1 = "1";
_bstr_t lParam2 = "2";

BSTR lValue;
for (int i=0; i<100000000; i++) {
int lResult = pPtr->getString(lParam1, lParam2, &lValue);
SysFreeString(lValue); // <-- NO LEAK!!
}
}


Willy.

Trokey said:
I've tried all these things, but no difference... I know there is a leak
because I monitor the private bytes in perfmon and the memory allocated by
the getString call is never released.

Matt

message news:[email protected]...
Trokey,

I don't see how the runtime is causing the leak. If anything, you need
to call SysFreeString to free the string.

You can also use a CComBSTR class and it will handle this automatically.

Also, you don't need to call the static Collect method on the GC class.

What do you have to support that there is a leak?


--
- Nicholas Paldino [.NET/C# MVP]
- (e-mail address removed)

Trokey said:
I am making interop calls to an object in a .NET component from a C++
program and am leaking memory... the following is some sample code:

////////////////////////////////////////
// .NET component (Test)
////////////////////////////////////////

// interface
[InterfaceType(ComInterfaceType.InterfaceIsDual)]
[Guid("D3DF5658-3D3F-436b-B6A6-F10E77AE3F5F")]
public interface IDotNetInterface
{
int getString(string aParam1, string aParam2, out string aValue);
}

// class
[ClassInterface(ClassInterfaceType.None)]
[ProgId("Test.DotNetInterface")]
public class DotNetInterface : IDotNetInterface
{
public int getString(string aParam1, string aParam2, out string aValue)
{
aValue = "some text";
GC.Collect();
return 1;
}
}

///////////////////////////////////
// C++ program
///////////////////////////////////

#import "Test.tlb" no_namespace named_guids

int _tmain(int argc, _TCHAR* argv[])
{
CoInitializeEx(NULL, COINIT_MULTITHREADED);

IDotNetInterfacePtr pPtr = IDotNetInterface(__uuidof(DotNetInterface));
pPtr->AddRef();

_bstr_t lParam1 = "1";
_bstr_t lParam2 = "2";

BSTR lValue;
int lResult = pPtr->getString(lParam1, lParam2, &lValue); // <-- LEAK!!

pPtr->Release();
pPtr = NULL;
}


I've tried all sorts of things (trying to explicitly release the BSTR
memory, etc.), but no effect. What is causing this leak, and how do I solve
it???

Thanks in advance,
Matt
 
T

Trokey

Thanks everyone... after putting the call in a loop, I can see that
SysFreeString solves the problem.

Matt

Willy Denoyette said:
int _tmain(int argc, _TCHAR* argv[])
{
CoInitialize(NULL);
IDotNetInterfacePtr pPtr(__uuidof(DotNetInterface));
_bstr_t lParam1 = "1";
_bstr_t lParam2 = "2";

BSTR lValue;
for (int i=0; i<100000000; i++) {
int lResult = pPtr->getString(lParam1, lParam2, &lValue);
SysFreeString(lValue); // <-- NO LEAK!!
}
}


Willy.

Trokey said:
I've tried all these things, but no difference... I know there is a leak
because I monitor the private bytes in perfmon and the memory allocated by
the getString call is never released.

Matt

message news:[email protected]...
Trokey,

I don't see how the runtime is causing the leak. If anything, you need
to call SysFreeString to free the string.

You can also use a CComBSTR class and it will handle this automatically.

Also, you don't need to call the static Collect method on the GC class.

What do you have to support that there is a leak?


--
- Nicholas Paldino [.NET/C# MVP]
- (e-mail address removed)

I am making interop calls to an object in a .NET component from a C++
program and am leaking memory... the following is some sample code:

////////////////////////////////////////
// .NET component (Test)
////////////////////////////////////////

// interface
[InterfaceType(ComInterfaceType.InterfaceIsDual)]
[Guid("D3DF5658-3D3F-436b-B6A6-F10E77AE3F5F")]
public interface IDotNetInterface
{
int getString(string aParam1, string aParam2, out string aValue);
}

// class
[ClassInterface(ClassInterfaceType.None)]
[ProgId("Test.DotNetInterface")]
public class DotNetInterface : IDotNetInterface
{
public int getString(string aParam1, string aParam2, out string aValue)
{
aValue = "some text";
GC.Collect();
return 1;
}
}

///////////////////////////////////
// C++ program
///////////////////////////////////

#import "Test.tlb" no_namespace named_guids

int _tmain(int argc, _TCHAR* argv[])
{
CoInitializeEx(NULL, COINIT_MULTITHREADED);

IDotNetInterfacePtr pPtr =
IDotNetInterface(__uuidof(DotNetInterface));
pPtr->AddRef();

_bstr_t lParam1 = "1";
_bstr_t lParam2 = "2";

BSTR lValue;
int lResult = pPtr->getString(lParam1, lParam2, &lValue); // <--
LEAK!!

pPtr->Release();
pPtr = NULL;
}


I've tried all sorts of things (trying to explicitly release the BSTR
memory, etc.), but no effect. What is causing this leak, and how do I
solve
it???

Thanks in advance,
Matt
 

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