[Mono-list] InteropServices: DllNotFoundException...?

Simon Ask Ulsnes simon@ulsnes.dk
Sun, 23 May 2004 16:56:33 +0200


(in-text)

Jonathan Pryor wrote:

>>Converting from char* to string seems to work great, could you elaborate 
>>on the memory issues that it might create?
>>    
>>
>
>That's because Mono, last I knew, was slightly buggy -- it doesn't
>properly free the memory.  .NET does.
>
>The deal is that class types such as System.String (as opposed to
>structure types) are always heap allocated.  As such, to prevent memory
>leaks when a class type is used as the return type of a function, two
>things are done: 
>
>  1: the data is marshaled from unmanaged to managed memory 
>     ("marshaled" == "copied, with some potential data transformation 
>     applied", such as converting Ansi strings to Unicode strings).
>
>  2: the unmanaged memory is freed.
>
>The problem is (2).  What memory manager is used?  If one memory manager
>allocates memory and another memory manager frees it, the heap could
>become corrupted.  This is bad.
>
>.NET uses CoTaskMemAlloc() and CoTaskMemFree() as the memory manager
>which crosses the managed/unmanaged boundary.  Mono will likely use
>g_malloc() and g_free(), but last I knew memory wasn't actually being
>freed.  This is probably why you're not seeing memory corruption. 
>Instead, you'd be seeing memory leaks.
>
>Again, see http://www.jprl.com/~jon/interop.html for more information.
>
>  
>
Ah, I see. Thanks for the explanation.

>>(I ended up using C++ simply because of the brilliant stream model, 
>>which makes handling of strings (with stringstream) so much more 
>>intuitive and easy).
>>Luckily, string.c_str() converts from string to char*... ;-)
>>    
>>
>
>Unfortunately, no.  std::string::c_str() converts to a "const char*". 
>Notice the "const"?  Furthermore, the memory returned by
>std::string::c_str() is managed by the std::string instance.  So if you
>attempted to manually free this memory (such as when the runtime
>marshals the returned string...), you'd get *at best* a double delete,
>and *at worst* heap corruption.
>
>Furthermore, if you do something like this:
>
>	const char*
>	get_my_string()
>	{
>		std::string s ("this is my string");
>		return s.c_str();
>	}
>
>You're *asking* for trouble, as the std::string destructor will free the
>memory used to hold the string, so the string returned by
>get_my_string() will be pointing to invalid memory.
>  
>
And guess what, that's actually what I'm doing (basically) - so far, it 
works, I haven't detected any memory leaks (haven't checked very 
thoroughly, though).
But you say using marshalling and IntPtr's is the best way to do it?

>  
>
>>But yes, I hope this is something that will be improved. Currently, it 
>>is extremely cumbersome to debug a C/C++ library through managed 
>>applications.
>>    
>>
>
>So don't. :-)
>
>Debug the unmanaged library in an unmanaged test application, and make
>sure the unmanaged part *actually works*.  Once that works, *then*
>introduce managed code.  To do otherwise is to greatly complicate your
>life, as you won't know where the problem is occurring.
>
>I would also suggest using valgrind, to help find memory leaks and
>memory corruption in your unmanaged code.
>
> - Jon
>
>
>_____________________________________________
>Mono-list maillist  -  Mono-list@lists.ximian.com
>http://lists.ximian.com/mailman/listinfo/mono-list
>
>  
>
Probably a good idea. ^_^

Yours,
Simon