[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