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.

10
  • I assume, copying any data around is not a solution? Commented Mar 22, 2013 at 13:08
  • @DanielHilgarth This is what I do right now, and no, it isn't. The performance hit is significant (if not paralysing) Commented Mar 22, 2013 at 13:15
  • @DanielHilgarth I am very reluctant to leave the managed world (i.e. go really native), but unsafe code is OK. Commented Mar 22, 2013 at 13:18
  • I deleted that comment in the meantime because I am not really sure how that would help. Commented Mar 22, 2013 at 13:19
  • What type does the third party code actually expect? byte[] or ArraySegment<byte>? Commented Mar 22, 2013 at 13:21

1 Answer 1

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>.

Sign up to request clarification or add additional context in comments.

8 Comments

As I mentioned in my Question: "Copying data back and forth is not a solution. It is the crutch I use right now though."
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.
@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).
Sorry to say so: #1, 3, 4 are explicitly excluded in the question, #2 was the question. Please elaborate on how to achieve this!
@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.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.