[Mono-devel-list] Re: [PATCH] Improper free of return-value string pointers from unmanaged calls
Jonathan Pryor
jonpryor at vt.edu
Fri Jun 11 06:58:15 EDT 2004
On Fri, 2004-06-11 at 01:32, Steven Brown wrote:
> Marcus wrote:
> > Freeing the string pointers is the appropriate behavior for .NET
> > compatibility.
>
> Could you give me a link to some docs that refer to that? It's
> empirically untrue as far as I can tell, as I can repeatedly call a
> method that dynamically allocates the returned string like:
Sure:
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpguide/html/cpconmemorymanagement.asp
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpguide/html/cpconpinvokelibdll.asp
(look for the TestStringAsResult() function, which
allocates memory using CoTaskMemAlloc().)
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpguide/html/cpconcreatingprototypesinmanagedcode.asp
In particular, from the last URL:
Note Win32 API functions that allocate a string enable you to
free the string by using a method such as LocalFree. Platform
invoke handles such parameters differently. For platform invoke
calls, make the parameter an IntPtr type instead of a String
type. Use methods provided by the
System.Runtime.InteropServices.Marshal class to convert the type
to a string manually and free it manually.
Alas, I couldn't find a *direct* reference stating "class used as return
types are always freed with CoTaskMemFree", but this is in fact the
case.
<sales mode="on">
As always, there's also my handy dandy guide, "Everything you (n)ever
wanted to know about Marshaling (and were afraid to ask!)", which also
covers this same issue. Find it at:
http://www.jprl.com/~jon/interop.html
</sales>
:-)
> MEMEAT_API char *foo(void)
> {
> static char *str = "Hello there";
> static int i = 0;
> char *newstr = (char *) malloc(strlen(str) + 1);
> strcpy(newstr, str);
> printf("%i: %s\n", i++, newstr);
> return newstr;
> }
This code is wrong for .NET anyway. Malloc/free isn't used under .NET;
CoTaskMemAlloc()/CoTaskMemFree() is.
<snip/>
> It doesn't make sense to free such a string pointer, as often string
> pointers will be coming from .rodata and such.
Actually, it *does* make sense, from a certain point of view. :-)
The perspective is that of RPC-like mechanisms, such as COM and CORBA,
which have certain notions about memory boundaries for remoting
purposes. "Out" memory, such as that return values and [Out]
parameters, must be allocated by the callee and freed by caller, as if
the caller/callee are in different processes/machines, the
runtime/remoting libraries will need to free this memory to avoid a
memory leak.
Alternatively, if they were to do as you ask, and NOT require the memory
allocation, you'd have an inconsistency. The remoting system would
*still* need to allocate memory (caller & callee are in separate
processes), and this memory must be freed to avoid a memory leak. So
you either require that the remoting system be omniscient and know when
to automatically free the memory, or you require that the caller
explicitly free the memory when required. The latter was chosen.
This would lead to a scenario where the caller frees memory that the
callee never allocated, which "works" in the remote scenario, but fails
miserably when caller/callee are in the same address space. Oops.
Given this, freeing the returned memory makes much more sense. This is
also why .NET uses CoTaskMemFree(), as that's the COM memory allocator.
- Jon
More information about the Mono-devel-list
mailing list