C# unsafe code

I’m curious about the support for unsafe code on .Net MF. This post suggests it works but I’m not clear on whether this is supported or inadvisable or what, the article is also a bit old now too.

Thanks

not supported as far as I know.

Yes, so it seems, I get an unresponsive board with legal unsafe code, simple code so I suspect its causing havoc. What I’m puzzled by is the apparent lack of any formal documentation of what specific C# features are support or not. For example I can’t find documentation for 4.3 that tells me:

  1. Can I use unsafe
  2. Can I use fixed size buffers
  3. Can I use async/await
  4. Can I use/define attributes

Its just not clear to me exactly what features are or are not available/supported and I think that if MS have neglected this then its a high priority to get this defined for us.

It seems fixed size buffers are not supported because the system attribute FixedBufferAttribute (applied implicitly to a member by the compiler) isn’t available in .Net MF.

This is a real shame because it allows the creation of a contiguous memory block with inline arrays (as opposed to reference fields pointing to distinct array objects).

unsafe and fixed buffers are incredibly useful when designing high performance code that is memory efficient, I’ve used these C# features to create seriaization APIs that are 10 * faster than protocol buffers, would be amazing to have access to these features in a tightly constrained hardware system like a Gadgeteer mainboard…

Officially it is not supported, but I use it to read and write doubles and longs from and to byte arrays.
So far it works. Tested on a G120.

It works for you on .Net MF 4.3?

I did some simple unsafe code yet the debugger hangs at the point of invoking the unsafe method. Others too are claiming it works but I wonder whether it still works on 4.3?

Thx

I only use an unsafe block inside a method, not methods with keyword unsafe.
like

;
long value = 5;
unsafe
{
   long* v = array[4];
   *v = value;
}

I’m not sure about the exact syntax, but something like the code above works for me.

On 4.3?

use of the above code requires pinning the target array, to avoid GC relocation, before getting a pointer. not sure the “fixed” keyword, or GC function, is supported with MF.

On Monday I can check how my code exactly looks.
But I know that the “fixed” keyword was compiled and working in 4.1.x, but I never tried if it really pins the array.

If ‘fixed’ is required then the compiler will insist upon it. Its not possible to get the address as a pointer without using ‘fixed’, Im guessing his example is pseudo code, dont think it wd compile…also the C# compiler is the same (I assume) whether we work on .Net MF or the std framework, I think the compiler is tied to the version of visual studio.

Ok, if you insist ::slight_smile:
Here is my actually working code, containing unsafe methods.
Tested with VS2012, VS2013, NETMF 4.2.x and NETMF 4.3.x.
Test with VS2015 is outstanding, but I don’t see why it shouldn’t work.
The project must of course be labeled as unsafe too.
It does not use “fixed”.
Actually I use this functions to convert double into ulong, then I split the ulong into two uints, which I copy into array with the utility class (not in this code).
But I already used “fixed” in NETMF 4.1.x and it did what I expected, I got the pointer which I passed to RLP.
But I can’t say for sure if the array was really pinned.

using System;
using Microsoft.SPOT;

namespace remes.Core
{
   public static class Conversion
   {
      public static unsafe float ToSingle(uint d)
      {
         float f = *(((float*)&d));
         return f;
      }

      public static ulong ToULong(uint dlow, uint dhigh)
      {
         return ((ulong)dhigh << 32) + (ulong)dlow;
      }

      public static double ToDouble(uint dlow, uint dhigh)
      {
         return ToDouble(ToULong(dlow, dhigh));
      }

      public static unsafe double ToDouble(ulong d)
      {
         double dbl = *(((double*)&d));
         return dbl;
      }

      public static unsafe uint ToUInt(float f)
      {
         uint ui = *(((uint*)&f));
         return ui;
      }

      public static unsafe ulong ToULong(double d)
      {
         ulong ul = *(((ulong*)&d));
         return ul;
      }

      public static void ToUInt(double d, out uint dlow, out uint dhigh)
      {
         ToUInt(ToULong(d), out dlow, out dhigh);
      }

      public static void ToUInt(ulong d, out uint dlow, out uint dhigh)
      {
         dlow = (uint)(d & 0x00000000ffffffff);
         dhigh = (uint)((d & 0xffffffff00000000) >> 32);
      }
   }
}

Looks to me like you don’t need ‘fixed’ because these are all stack-based scalar values - not heap-based ref values. So, you’re both right. The compiler will insist on ‘fixed’ in cases when it is needed, and this isn’t one of those cases.

I always wanted to test the following scenario.

  • Create a managed array
  • spawn a thread, fix the array there, hand it over to RLP and sleep for ever inside the fixed block
  • wildly allocate memory in managed code and run GC
  • see if pointer in RPL still points to the correct address by writing something to pointer in RLP and read it back in managed code.

Then do the same without staying in the fixed block by a sleep, to see if the test is sufficient to force array movement in RAM.

Edit: But I guess it would be easier to create this “shared buffer” as an large array, because this one would not be touched by GC. Right?

The ‘fixed’ is required if the target address could be GC moved. Value type args passed by value, stack based value types etc dont need ‘fixed’ because they’ll never move. If you have a class with value type private fields, code in that class will need ‘fixed’ to take the field’s address simply because the object (containing the field) could move and with it it’s fields. If you examine the associated IL you’ll see that ‘fixed’ really causes the creation of a [em]pinned [/em]reference, an IL concept visible in C# only via the ‘fixed’ keyword.

My own test that crashed the board, took the adress of a local stack struct, let me retest in light of your code.

Thanks for taking the time to post all that.

OK there may be a bug in their CLR implementation - bit of a claim though considering [em]unsafe [/em]is deemed unsupported!

The system crashes if we take the address of a local (stack) variable, but is fine when we take the address (pinned) of a member field or (as you’ve shown) take the address of a value type arg.

Being able to get at the address of member fields is much more useful anyway.

It is what it is I guess…

Well, the address of a local stack variable is only valid as long as you don’t leave the method.
A value type parameter is also on the stack.

All true, returning a pointer to such an item would lead to problems, but freezing just by getting an address is not normal behavior. Im guessing that this indicates that unsafe code is simply not fully implemented in this CLR.