Simple question here: is there any way to convert from a jagged array to a double pointer?
e.g. Convert a double[][]
to double**
This can't be done just by casting unfortunately (as it can in plain old C), unfortunately. Using a fixed
statement doesn't seem to resolve the problem either. Is there any (preferably as efficient as possible) way to accomplish this in C#? I suspect the solution may not be very obvious at all, though I'm hoping for a straightforward one nonetheless.
I've gone with zachrrs solution for the time being (which was what I was suspecting might need to be done in the first place). Here it is an extension method:
A little bit of safety.
As mentioned in comments to the first solution, nested arrays could be moved, so they should be pinned too.
A brief explanation of the problem:
When we allocate some objects on the heap, they could be moved to another location on garbage collecting. So, imagine next situation: you have allocated some object and your inner arrays, they are all placed in zero generation on the heap.
Now, some object has gone from scope and became garbage, some objects just been allocated. Garbage collector will move old objects out of heap and move other objects closer to the begging or even to the next generation, compacting heap. The result will looks like:
So, our goal is to “pin” some objects in heap, so they would not move. What we have to achieve this goal? We have fixed statement and GCHandle.Allocate method.
First, what
GCHandle.Allocate
does? It creates new entry in inner system table that have a reference to the object that passed to method as a parameter. So, when garbage collector will examine heap, he will check inner table for entries and if he will find one, he will mark object as alive and will not move it out of heap. Then, he will look on how this object is pinned and will not move the object in memory in compacting stage.fixed
statement does almost the same, except it “unpins” object automatically when you leave scope.Summarizing: each object that has been pinned with
fixed
will be automatically “unpinned” once he left a scope. In our case, it will be on next iteration of loop.How to check that your objects will not be moved or garbage collected: just consume all the heap's budget for zero generation and force GC to compact heap. In other words: create a lot of objects on the heap. And do it after you pinned your objects or “fixed” them.
Small notice: there are two types of heaps — for large objects and for small ones. If your object is large, you should create large objects to check your code, otherwise small objects will not force GC to start garbage collection and compacting.
Lastly, here's some sample code, demonstrating the dangers of accessing the underlying arrays with unpinned/unfixed pointers - for anybody who is interested.
A double[][] is an array of double[], not of double* , so to get a double** , we first need a double*[]
I can't help but wonder what this is for and if there is a better solution than requiring a double-pointer.