[Mono-dev] "safe" way about Marshal.UnsafeAddrOfPinnedArrayElement

Kornél Pál kornelpal at gmail.com
Tue Apr 18 08:13:36 EDT 2006


Hi,

Unsafe code usually means code that uses pointers. But that unsafe code has 
to use the fixed statement when accessing objects that can be moved. fixed 
statement pins the object so that GC will not move it within the block of 
fixed statement. (As far as I know Mono still uses non-moving GC but that 
will change in the future and MS.NET uses moving GC.)

Marshal.UnsafeAddrOfPinnedArrayElement is unsafe in addition to pointer 
operations because it assumes that the array is already pinned so it won't 
(an in fact can't as it has no scope) pin the object so the GC can move it 
that can result in invalidation of the returned pointer so has to be used 
carefully. (When the array is moved by the GC you can overwrite some other 
object that can have unpredictable results.)

Marshal.UnsafeAddrOfPinnedArrayElement is intended to be used with a pinned 
GCHandle. (Or alternatively on an array that is already pinned using fixed 
statement but in that case you have a pointer to an array element so you 
probably don't need this method.)

If you have a non-pinned array you should use fixed statement instead as 
Jonathan explained it.

So Marshal.UnsafeAddrOfPinnedArrayElement is even more unsafe than unsafe 
code when used on a non-pinned array.

Kornél

----- Original Message ----- 
From: "Jonathan Pryor" <jonpryor at vt.edu>
To: "GaoXianchao" <gxcmaillist at gmail.com>
Cc: <mono-devel-list at lists.ximian.com>
Sent: Tuesday, April 18, 2006 1:48 PM
Subject: Re: [Mono-dev] "safe" way about 
Marshal.UnsafeAddrOfPinnedArrayElement


> On Tue, 2006-04-18 at 12:27 +0800, GaoXianchao wrote:
>> hi all,
>> I'm wrapping epoll api on linux.
>> To pass address of managed struct array to unmanaged code, I use
>> Marshal.UnsafeAddrOfPinnedArrayElement . But the method is "unsafe".
>> Is there a "safe" way to do what the 
>> Marshal.UnsafeAddrOfPinnedArrayElement do?
>
> It's "unsafe" because you need to be careful. :-)
>
> An alternative is to use *real* unsafe code, e.g.
>
> FooStruct[] array = ...;
> unsafe {
> fixed (FooStruct* pArray = array) {
> FooStruct* element = &pArray [index];
> }
> }
>
> I'm not entirely sure what your problem is though.  "Unsafe" code (like
> the above `unsafe' block) just means that you're possibly executing
> without a net, which could result in memory corruption and abortion of
> the process. :-)
>
> Marshal.UnsafeAddrOfPinnedArrayElement isn't even in an unsafe C#
> context, it just has "Unsafe" in the name.
>
> Here's a hint of truth: ANY time you do a P/Invoke, you're potentially
> doing something unsafe. :-)
>
> (Especially considering that you're invoking external code which could
> really do anything, such as overwrite the entire GC heap, which would
> cause the process an ugly death in the future...)
>
> However, I'm not sure why you need
> Marshal.UnsafeAddrOfPinnedArrayElement in the first place.
> epoll_wait(2) takes a `struct epoll_event' array parameter, so unless
> you wanted to only send a subset of your array, the default marshaling
> rules which convert a managed array to an array pointer should be fine.
>
> - Jon
>
>
> _______________________________________________
> Mono-devel-list mailing list
> Mono-devel-list at lists.ximian.com
> http://lists.ximian.com/mailman/listinfo/mono-devel-list 




More information about the Mono-devel-list mailing list