Memory leak in interop

  • Thread starter Thread starter Trokey
  • Start date Start date
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
 
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?
 
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
 
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
 
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
 
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
 
Back
Top