Link to home
Start Free TrialLog in
Avatar of Xtreem
XtreemFlag for United Kingdom of Great Britain and Northern Ireland

asked on

Managing unmanaged memory assigned to IntPtr by Marshal::AllocHGlobal when an exception is thrown

I have the following code:

using namespace System::Runtime::InteropServices;
void CRCWAssembly::CallCOMMethod(long __gc* status)
{
    try
    {
        IntPtr ip = Marshal::AllocHGlobal(sizeof(*status));
        Marshal::WriteInt32(ipStatus, *status);
        (*comLib)->COMMethod(static_cast<long*>(ipStatus.ToPointer()));

        if (Marshal::ReadInt32(ipStatus) != 0)
        {
            throw new Exception();
        }
        Marshal::FreeHGlobal(ip);
    }
    catch(SEHException *sehEx)
    {
        throw new Exception("COMMethod", sehEx);
    }
}

Of course, if an exception is thrown, the memory allocated to ip (IntPtr) never gets freed up. Short of wrapping it up in a class or putting Marshal::FreeHGlobal all over the place and moving the declaration of ip to outside of the 'try' block, is there any other better method to manage this unmanaged memory in the case of an exception being thrown?
Avatar of Xtreem
Xtreem
Flag of United Kingdom of Great Britain and Northern Ireland image

ASKER

I've changed the code to this now:

using namespace System::Runtime::InteropServices;
void CRCWAssembly::CallCOMMethod(long __gc* status)
{
    IntPtr ip;
    try
    {
        ip = Marshal::AllocHGlobal(sizeof(*status));
        Marshal::WriteInt32(ipStatus, *status);
        (*comLib)->COMMethod(static_cast<long*>(ipStatus.ToPointer()));

        if (Marshal::ReadInt32(ipStatus) != 0)
        {
            throw new Exception();
        }
        Marshal::FreeHGlobal(ip);
    }
    catch(Exception *ex)
    {
        Marshal::FreeHGlobal(ip);
        throw new Exception("COMMethod", ex);
    }
}

But I'm still not sure that this is the ideal solution. Any more insight greatly appreciated...
ASKER CERTIFIED SOLUTION
Avatar of AlexFM
AlexFM

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of Xtreem

ASKER

Thanks AlexFM.

I used Marshal as I am working between managed memory (*status, being passed from a C# application) and unmanaged memory (ipStatus, being passed to a COM API). This code is in the CRCW (Customer Runtime Callable Wrapper).

If I can use an unmanaged long, why does this page on MSDN show the same method I'm using for calling a COM method from a CRCW?: http://msdn2.microsoft.com/library/f31k2c87.aspx

Also, are you saying I should use Marshal::SizeOf instead of sizeof to get the size of *status?
SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of Xtreem

ASKER

Oh, I see. Well, I'd like to be consistent and make my code easily portable to other .NET languages, so for this case, I'll change sizeof to Marshal::SizeOf.

Thanks!