3

My unsafe method accepts a collection byte[]s. All of these byte[]s are of the same size.

I need to iterate over them all, searching for certain patterns. The search is inherently reinterpret-cast style: at each offset, I need to consider a value as if it were a float, a double, a short, an int, etc. So getting a byte* for each input byte[] and incrementing it on each iteration seems like a natural approach.

Unfortunately I can't find any way to create a collection of byte* - or, more specifically, to initialize it from a collection of arrays. Any ideas?

Here's a somewhat contrived version of the task:

static unsafe void SearchIteration(List<byte[]> arrays, byte[] resultArr)
{
    fixed (byte* resultFix = resultArr)
    {
        byte* resultPtr = resultFix;
        byte*[] pointers = new byte*[arrays.Count];

        <some code to fix all the arrays and store the pointers in "pointers">

        int remaining = resultArr.Length;
        while (remaining > 0)
        {
            <look at resultPtr and each of the pointers and update *resultPtr>

            remaining--;
            for (int i = 0; i < pointers.Length; i++)
                pointers[i]++;
        }
    }
}

Essentially the question is how to initialize pointers with the addresses of arrays, while pinning the arrays so that GC doesn't move them.

8
  • What exactly is your collection of objects, and what are in the byte[] ? Commented Aug 24, 2010 at 20:23
  • Do you really need to have all byte[] in arrays to be pinned at the same time, or could you process them one after another? Commented Aug 24, 2010 at 20:28
  • @Raynos sorry for confusion, I simplified a bit and forgot to remove one reference to "objects". Gone now. Just byte[]s. Commented Aug 24, 2010 at 20:32
  • @dtb yes, I need to compare them all to each other. For example, at a given offset, check if all offsets interpreted as floats represent the same float within a range of, say, +/- 10.0f. Commented Aug 24, 2010 at 20:34
  • BitConverter is too slow for your purpose? msdn.microsoft.com/en-us/library/… Commented Aug 24, 2010 at 20:35

1 Answer 1

2

use GCHandle.Alloc() from System.Runtime.InteropServices:

var handles = new GCHandle[arrays.Count];
byte*[] pointers = new byte*[arrays.Count];
for(int i = 0; i < arrays.Count; ++i)
{
    handles[i] = GCHandle.Alloc(arrays[i], GCHandleType.Pinned);
    pointers[i] = (byte*)handles[i].AddrOfPinnedObject();
}
try
{
    /* process pointers */
}
finally
{
    for(int i = 0; i < arrays.Count; ++i)
    {
        handles[i].Free();
    }
}
Sign up to request clarification or add additional context in comments.

2 Comments

That pins the objects. But where does the pointer point to (the array content or the CLR object header of the array object)?
it points to exatly what you are expecting - first array element

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.