1

Before diving into the question itself, please understand, that I am not in control of the whole food chain here - answers or comments of the "you are doing it wrong" kind won't help, as I need to develop against a given API.

Components, that communicate chunks of raw data, most often do so via buffers of type byte[] or ArraySegment<byte>. The latter has the big advantage of being able to allocate a big buffer once and for all, then use parts of it via the ArraySegment mechanism to reduce memory allocation, fragmentation and GC problems. Nothing new here.

This comes at a price though: A (possibly foreign, closed-source) component consuming an ArraySegment<byte> gets a reference (and thus access) to the complete array, meaning, that if it misbehaves it has the ability to corrupt completly unrelated buffers.

Now:

  • An extensive search revealed no mechanism to expose only a part of an existing array as a complete array, this SO question was the closest I got, still not usable as it is "not an array".
  • Inheriting from System.Array is not supported.
  • Inheriting from System.ArraySegment<T> is not supported either.

My chain of questions is (answering one obsoletes the later ones):

  • Is there a "tricky" way to present a self-developed wrapper as a byte[] to a (foreign) consumer
  • Or is there a "tricky" way to present a self-developed wrapper as an ArraySegment<byte> to a (foreign) consumer, that will not expose the complete underlying array
  • Alternativly, is there a way to inherit from System.Array, that I missed
  • Again alternativly: Is there a way to create a byte[] from an aleady allocated (and pinned) memory region, that I have missed, that will not screw up, if it is GCed

Edit:

From the comment I take, I didn't say it expressivly enough. Copying data back and forth is not a solution. It is the crutch I use right now though.

Community
  • 1
  • 1
Eugen Rieck
  • 64,175
  • 10
  • 70
  • 92

1 Answers1

0

Edit: To clarify, your options are

  • Rewrite the external library to not hard-code T[] / ArraySegment<T>
  • Choose a different way to segment your buffers so calls to the external library naturally align with buffer sizes
  • Accept that your over-sized buffers expose additional data that is vulnerable to corruption by outside code
  • Copy data

Edit 2: Leaving no doubt

Is there a "tricky" way to present a self-developed wrapper as a byte[] to a (foreign) consumer

No, you cannot do this.

Or is there a "tricky" way to present a self-developed wrapper as an ArraySegment to a (foreign) consumer, that will not expose the complete underlying array

No, you cannot do this.

Alternativly, is there a way to inherit from System.Array, that I missed

No, you cannot do this.

Again alternativly: Is there a way to create a byte[] from an aleady allocated (and pinned) memory region, that I have missed, that will not screw up, if it is GCed

No, you cannot do this.


Without changing the external API, this becomes by original answer:

If you are stuck using arrays and wish to prevent other code from accessing the sections of the array outside the allowed bounds, you must do the following:

T[] originalData = ...;
int viewStart = ...;
int viewLength = ...;

// use a separate array for the viewable region
T[] view = new T[viewLength];
Array.Copy(originalData, viewStart, view, 0, viewLength);
ArraySegment<T> segment = new ArraySegment<T>(view).

// call other code
...

// apply changes
Array.Copy(view, 0, originalData, viewStart, viewLength);

These are the restrictions you were placed under due to the API designer's choice to use T[]/ArraySegment<T> instead of IList<T>.

Sam Harwell
  • 97,721
  • 20
  • 209
  • 280
  • As I mentioned in my Question: *"Copying data back and forth is not a solution. It is the crutch I use right now though."* – Eugen Rieck Mar 22 '13 at 15:37
  • In addition to that, I currently use a single (big enough) temp array per thread, to avoid allocating and GCing for every single call. Doing it the given way would be another step back. – Eugen Rieck Mar 22 '13 at 15:41
  • @EugenRieck I didn't misread your question. Your question as posed does not have a solution, so I posted an explanation instead (also note the edit). – Sam Harwell Mar 22 '13 at 15:43
  • Sorry to say so: #1, 3, 4 are explicitly excluded in the question, #2 was the question. Please elaborate on how to achieve this! – Eugen Rieck Mar 22 '13 at 16:07
  • @EugenRieck You didn't ask about #2. #2 means never allocate such large buffers in the first place. Instead of allocating over-sized buffers, allocate buffers the exact size you will need for calling the external API. – Sam Harwell Mar 22 '13 at 16:15
  • Which is exactly the second paragraph of my Question. Let's leave it at that and move on - thank you for your "answer", which can be summarized as "I don't know" – Eugen Rieck Mar 22 '13 at 16:19
  • @EugenRieck Please see my Edit 2. If you have further questions please be specific. – Sam Harwell Mar 22 '13 at 16:29
  • @EugenRieck Also, before claiming that "I don't know", see my answer on the following question: http://stackoverflow.com/questions/2040118/find-the-length-of-an-array-without-using-the-length-property/2082773#2082773 – Sam Harwell Mar 22 '13 at 16:31