Suppose there is an array of bytes

byte[] bytes = new byte[] { 1, 2, 3, 4, 5, 6, 7, 8 }; 

and such

 [StructLayout(LayoutKind.Explicit)] struct ByteToUlongConverter { [FieldOffset(0)] public byte[] bytes; [FieldOffset(0)] public ulong[] ulongs; public ByteToUlongConverter(byte[] bytes) { this.ulongs = null; this.bytes = bytes; } } 

structure.

Next, using this structure, I do

 ByteToUlongConverter conv = new ByteToUlongConverter(bytes); foreach (ulong ul in conv.ulongs) Console.WriteLine($"{ul:X16}"); 

This displays something like

 0807060504030201 793C086C00000000 0000000000000000 0000000000000000 0000000000000000 0000000004710B40 00000001793BFDD8 793BED0C00000000 

Those. I allocated 8 bytes, and read 64 (you can not only read, but write something).

These extra bytes are they whose? What is this memory? Those. as far as I understand my array is somewhere in the heap, and this is something that lies nearby. A heap in .Net as organized, is it one for all processes or does each process have its own heap? Those. Can another process, without special privileges, try to consider something in my process in this way?

  • Hmm, on IdeOne reproduced: ideone.com/0CNmCS Some kind of nonsense , okay, it would be an unsafe code ... - Pavel Mayorov
  • Yes, the inclusion of the "Allow unsafe code" flag is not required. - i-one

2 answers 2

You are right, this is the memory from the heap, located just after the byte array. A heap in .NET is one for each application domain, or, relatively speaking, one for one application. The garbage collector works with a heap, and it would not be very good if, due to a neighboring application, your application also had to be stopped to free up memory.

However, please note that the process and application domain are different concepts. A process is the structure of the Windows kernel, and within one process there can be many application domains, because they are (supposedly) managed — that is, they cannot simply get into each other’s memory. But since this is a single Windows process, then theoretically they can of course spoil the memory of each other if they use unmanaged code.

Therefore, .NET does not allow unmanaged code to run just like that (see the Security section in An Overview of Managed / Unmanaged Code Interoperability ). Another process cannot get into your memory due to hardware limitations, and the other application domain will not be able to, unless you explicitly allow it.

By the way, the heap is also not the usual sequence of blocks - to increase the performance of garbage collection, it is divided into two parts: for small objects and for large objects.

Now specifically about your code. You have two arrays at the same address. In .NET, the size of the array is stored at the very beginning, it is allocated 8 bytes, that is, a number of type System.Int64 . The original array has a length of 8. When you try to work with this array, as with the ulong 's array, the length remains the same, that is, 8, but the elements themselves become 8 times larger. Therefore, you can read 8 Ă— 8 bytes instead of 8.

But sometimes an exception may occur, due to the fact that the array passes along the border of the segment allocated by the operating system, and this will be a purely hardware exception. If you try to write something to the ulong array, the behavior will be unpredictable. Each block in the heap is preceded by a service header, so the 9th byte can have such a header and is located, respectively, the application may fall during the next garbage collection.

  • one
    The best answer. From a stranger reader thanks! - V. Dmitriy
  • In general, yes - where I use it, I not only read the converted array, but also write to it. I think that this is not bad, if you do not go beyond the bounds of the array (by ulongs I go in a cycle from zero to bytes.Length/sizeof(ulong) plus a “tail” by bytes in length bytes.Length%sizeof(ulong) ). It became, however, interesting - what is there beyond the border of the array and whose it is. - i-one
  • @ i-one, look towards the BitConverter.ToUInt64 method. It will work a little slower, but the method is safe and standard. - Mark Shevchenko
  • BitConverter, as far as I can see, allows you to read the data in the array "in place", but, unfortunately, it does not have a similar method that allows you to change the data in the array (i.e., to roll ulong into 8 bytes of the array at once ). However, just reading is also useful here and there. - i-one
  • If you need to convert an array of long integers into an entire byte array, you can try ulongArray.SelectMany(BitConverter.GetBytes).ToArray() . This is slower than direct memory manipulation, but, as I already wrote, this is managed code that can be run everywhere, because it will not break anything. - Mark Shevchenko

The array was allocated in a managed heap. The first line of output shows, in fact, the original array of bytes.

This means that the remaining lines contain a random fragment of a managed heap.


PS do not use similar hacks for conversion, use better BitConverter