Comments: Yet another reason to love C#

Hi,

I have my method written in win32 dll with extern "C". I do pInvoke from C#. The dll allocates memory using CoTaskMemAlloc and in C# I get it as a string. I am not calling CoTaskMemFree as I do not know from where to call from C#. Finally when I close the dialog I get either Outofmemory exception or stackoverflow exception. One such exception message is: An unhandled exception of type 'System.OutOfMemoryException' occurred in mscorlib.dll.

How to overcome this problem. Here is the code similar to the one I have in my application.

I have written below the sample code. My actual application is some what similar to it.

In the code below I am allocating 1024 byte of memory for each value of i in the loop. But in the actual application this is a variable size.

Thank you so much for your assistance.
===========

Code Snippet:

in C#:

//Declaration & Definition
public struct User
{
public string m_strNameFirst;
public string m_strNameLast;
public double m_dAge;
}

[DllImport( "MyDLL.dll", SetLastError=true, ExactSpelling = true, CharSet = CharSet.Ansi)]
public static extern string GetUserList( [In, Out] User[] pUser, int iCount);

[DllImport( "MyDLL.dll", SetLastError=true, ExactSpelling = true, CharSet = CharSet.Ansi)]
public static extern string GetUserCount( ref int iCount);

public void understandPInvoke()
{
int iCount=0;
string strStatus = GetUserCount( ref iCount);

if( iCount User[] users = new User[iCount];
strStatus = GetUserList( users, iCount);
//when the user closes the dialog in where the above code exists, I copy this User structure name in my objects and use it in my application. I do not free any memory in my C# code.
}

C++ dll: (win32 dll):

struct CPP_User
{
char* pNameFirst;
char* pNameLast;
double dAge;
};

extern "C" MYDLL_API char* GetUserCount( int *pNumberOfUsers);
extern "C" MYDLL_API char* GetUserList( CPP_User pUsers[], int iCount);

char *PrepareStatus( char* pStatus)
{
char *strOutMsg = (char *)CoTaskMemAlloc( sizeof(char) * strlen( pStatus) + 1);
strOutMsg[0]=0;
strcpy( strOutMsg, pStatus);
return strOutMsg;
}

extern "C" MYDLL_API char* GetUserCount( int *pNumberOfUsers)
{
pNumberOfUsers = 99999;//This number can be huge but less than the max value of the int.
return PrepareStatus( "Success");
}


extern "C" MYDLL_API char* GetUserList( CPP_User pUsers[], int iCount)
{
for( int i=0; i {
CoTaskMemFree( pUsers[i].pNameFirst);
CoTaskMemFree( pUsers[i].pNameLast);

char *strName1 = (char *)CoTaskMemAlloc( sizeof(char) * 1024); //in my application this size is a variable one it will not be always 1024.
char *strName2 = (char *)CoTaskMemAlloc( sizeof(char) * 1024);
sprintf( strName1, "%s %i", "George", i);
sprintf( strName2, "%s %i", "Bush", i);

pUsers[i].pNameFirst = strName1;
pUsers[i].pNameLast = strName2;

pUsers[i].dAge = 30;
}

return PrepareStatus( "Success");
}

Posted by Ganapathi Raman at March 31, 2005 08:51 AM