0

First, basic info on our environment: We're using c# .net 4.0, on Win7-x64, targeting 32-bit.

We have a preallocated -large- array. In a function, we would like to return a pointer to an arbitrary point in this array, so that the calling function can know where to write. Ex:

class SomeClass {
    void function_that_uses_the_array() {
       Byte [] whereToWrite = getEmptyPtrLocation(1200);
       Array.Copy(sourceArray, whereToWrite, ...);
    }
}

class DataProvider {
    int MAX_SIZE = 1024*1024*64;
    Byte [] dataArray = new Byte[MAX_SIZE];
    int emptyPtr=0;
    Byte[] getEmptyPtrLocation(int requestedBytes) {
       int ref = emptyPtr;
       emptyPtr += requestedBytes;
       return dataArray[ref];
    }
}

Essentially, we want to preallocate a big chunk of memory, and reserve arbitrary length portions of this memory block and let some other class/function to use that portion of memory.

In the above example, getEmptyPtrLocation function is incorrect; it is declared as returning Byte[], but attempting to return a single byte value.

Thanks

0

5 Answers 5

4

As others have said, you can't do this in C# - and generally you shouldn't do anything like it. Work with the system - take advantage of the garbage collector etc.

Having said that, if you want to do something similar and you can trust your clients not to overrun their allocated slot, you could make your method return ArraySegment<byte> instead of byte[]. That would represent "part of an array". Obviously most of the methods in .NET don't use ArraySegment<T> - but you could potentially write extension methods using it as the target for some of the more common operations that you want to use.

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

4 Comments

I heard the garbage collector argument a few times, but our testing so far shows that pre-allocating does help. Could it be very dependent on the characteristics of the application? In our application, we need to allocate/deallocate between 2K-128K of memory (different sizes every time), at around 250 times per second.
@SomethingBetter: Have you considered preallocating complete arrays of various sizes, and allowing the caller to just get a buffer of a different size, rather than a subarray within one big array?
Maybe, but the lengths vary greatly and it causes a lot of fragmentation/empty space. Actually, one of my fundamental problem is that I can't read data into an arbitrary position into an array, since we're using a 3rd party library. I've posted that as another question here: http://stackoverflow.com/questions/4895799/pinvoke-pointers-and-array-copy. I'd appreciate any insight. --thanks
@SomethingBetter: It's relatively unusual for an API like that not to take an index into the array (like Stream.Read does). In terms of your fragmentation issue - if you have "bands" of buffers, it needn't have too much effect. You can waste some space without wasting vast amounts.
4

Quite old post this is but I have an easy solution. I see that this question has lot's of answers like "you shouldn't". If there is a method to do something, why not use it?

But that aside, you can use the following

int[] array = new int[1337];
position = 69;
void* pointer = (void*)Marshal.UnsafeAddrOfPinnedArrayElement(array, position);

Comments

3

This is C# not C++ - you are truly working against the garbage collector here. Memory allocation is generally very fast in C#, also it doesn't suffer from memory fragmentation one of the other main reasons to pre-allocate in C++.

Having said that and you still want to do it I would just use the array index and length, so you can use Array.Copy to write at that position.

Edit:

As others have pointed out the ArraySegment<T> fits your needs better: it limits the consumer to just his slice of the array and it doesn't require to allocate a separate array before updating the content in the original array (as represented by the ArraySegment).

3 Comments

Agree on the sentiment (this shouldn't be done), disagree on the use of Array.Copy. That allocates new memory, it doesn't return a subset of the array. From MSDN: msdn.microsoft.com/en-us/library/k4yx47a1.aspx
@Chris: Agreed - Array.Copy would require the class that's using it to allocate their own buffer before copying it to the target buffer, also they would have access to the full array - so yes an ArraySegment would be preferable.
@jon, @Chris, @BrokenGlass: Thanks for the info on ArraySegment<T>, first time I heard about this class. Although, it does not appear to be very useful. Turns out, you cant index an ArraySegment with [], nor you can iterate over it. Apparently, you have to access ArraySegment.Array field, and then index it with [], with the index ids being the original array indices!. Here is a good link
2

Without going into unmanaged code, you can't return a pointer to the middle of the array in C#, all you can do is return the array index where you want to enter the data.

Comments

1

If you must do this, your options include returning an ArraySegment (as Jon Skeet pointed out), or using Streams. You can return a MemoryStream that is a subset of an array using this constructor. You will need to handle all of your memory reads and writes as stream operations however, not as offset operations.

Comments

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.