I am attempting to call functions within an unmanaged C library fromVB.NET.Both input and outputarguments to the C library functions are by-reference ANSI BSTRs, the memory for which is managed within the C library using SysAllocStringByteLen() and SysFreeString().In VB.NET, I am declaring the functions like this:
Declare Functionfcn_name Lib "lib_name.dll" ( _
<MarshalAs(UnmanagedType.AnsiBStr), [In]()> ByRefInArg As String, _
<MarshalAs(UnmanagedType.AnsiBStr), Out()> ByRefOutArg As String) _
As Int
On x86, this works as expected.
On x64, memory issues arise. When run on x64 XP/Server 2003, the returned unmanaged AnsiBStr never gets free'd after conversion to the managed OutArg. When run on x64 Vista/Server 2008, the heap gets corrupted.
If instead I manage the output marshaling myself, such as first defining:
Friend Module LIBMOD
Declare Functionfcn_name Lib "lib_name.dll" ( _
<MarshalAs(UnmanagedType.AnsiBStr), [In]()> ByRefInArg As String, _
<Out()> ByRefOutPtr As IntPtr) _
As Int
End Module
and then defining the function called within the code to be:
Private Function fcn_name( _
ByRefInArg As String, _
ByRefOutArg As String) _
As Int
DimOutPtr As IntPtr
Dim retval As Int
retval = LIBMOD.fcn_name(InArg, OutPtr)
IfOutPtr <> 0 Then
OutArg = Marshal.PtrToStringAnsi(OutPtr)
Marshal.FreeBSTR(OutPtr)
End If
Return retval
End Function
this works without fault on x64: FreeBSTR() is calling SysFreeString() on the unmanaged output, and neither memory leaks nor heap corruption occur.
This is more or less equivalent to what I'd expect to happen in the first case, but it seems as if the x64 framework is utilizing some mechanism other than SysFreeString() to free the returned AnsiBStr's.
Should two approaches be equivalent? If not, why the does the first work on x86 but not x64?