- Home /
Multidimensional array debugging error
I have a multidimensional array that I initialize like this:
bool[,] arr = new bool[7,7];
This works fine. However, when i try to assign to this variable:
arr[3,3] = true;
The debugger will step out of the function I am in with in the next few lines of code. it does not throw an exception (I put in a try/catch), and the code executes, but it refuses to allow me to debug further. If I use a list>, instead of a multidimensional array everything works fine. Obviously, I don't want to resort to this. Anyone know why this is happening?
I changed it to a jagged array ( bool[][] arr ) and that works fine too. For now that is what i'm going with but this is still very puzzling to me.
Answer by Bunny83 · Nov 10, 2017 at 06:23 PM
Multidimensional arrays are behind the scenes just normal flattened arrays with some additional index calculation. So they store the size of each dimension which is used whenever you read or write. I'm sure this "extra code" (which is most likely inlined in the final build) can't be properly debugged.
Have a look at this example:
public class MultiDimArrayDebug : MonoBehaviour
{
bool[,] testArray;
bool[] normalArray;
void Start ()
{
testArray = new bool[7, 7];
testArray[3, 3] = true;
normalArray = new bool[49];
normalArray[3 + 3 * 7] = true;
}
}
The Start method when it's compiled to IL looks like this:
.method private hidebysig instance void Start () cil managed
{
.maxstack 8
IL_0000: nop
IL_0001: ldarg.0
IL_0002: ldc.i4.7
IL_0003: ldc.i4.7
IL_0004: newobj instance void bool[0..., 0...]::.ctor(int32, int32)
IL_0009: stfld bool[0..., 0...] MultiDimArrayDebug::testArray
IL_000e: ldarg.0
IL_000f: ldfld bool[0..., 0...] MultiDimArrayDebug::testArray
IL_0014: ldc.i4.3
IL_0015: ldc.i4.3
IL_0016: ldc.i4.1
IL_0017: call instance void bool[0..., 0...]::Set(int32, int32, bool)
IL_001c: ldarg.0
IL_001d: ldc.i4.s 49
IL_001f: newarr [mscorlib]System.Boolean
IL_0024: stfld bool[] MultiDimArrayDebug::normalArray
IL_0029: ldarg.0
IL_002a: ldfld bool[] MultiDimArrayDebug::normalArray
IL_002f: ldc.i4 24
IL_0034: ldc.i4.1
IL_0035: stelem.i1
IL_0036: ret
} // end of method MultiDimArrayDebug::Start
0002 to 0004 is actually a call to constructor which creates the multidimensional array.
0001 + 0009 store the resulting object in the field of my testing class
000e +000f load the reference to the array back on the stack
0014 to 0017 call the Set method of the multidimensional array
So setting the value of a multidimensional array actually invokes a method which performs the setting of the value. This method is auto generated by the framework. Now have a look at a "normal" one dimensional array:
001c to 0024 creates a new bool array and stores it in the field
0029 + 002a loads the reference from the field back on the stack
002f to 0035 sets the array element to "true" (1).
As you can see normal / one dimensional arrays have native support. The creation as well as the read and write of elements are actually opcodes (newarr--> new array, stelem --> store element ). However multidimensional arrays are actually framework generated wrapper classes around a normal native array. How those are actually implemented is an implementation detail of the framework. Those wrapper classes do not actually exist anywhere as there would be a countless amount of them. Keep in mind that you can create an "n" dimensional array where n can go up to "32".
Some more information on debugging
When you debug the example code i've posted you have to keep in mind that the code that is actually executed is the IL code (which is actually JIT compiled to native code) and not the C# source code. The debugger has to match up the actual emitted opcodes with the source code line. This can easily go wrong, especially when different compilers are involved.
VisualStudio somehow executes those two lines:
testArray = new bool[7, 7];
testArray[3, 3] = true;
at once instead of one after another. So it seems VS as trouble to actually keep the code and source in sync. However if you place a breakpoint on each line and instead of "Step over" or "Step into" you just use "continue" (F5) it will properly execute line by line.
Fun fact: You can actually create a multidimensional array with only one dimension. Note that this is different from a native one dimensional array. Have a look at the "Note" in the "Remarks" section.
The breakpoints everywhere option, though tedious may be the way I have to go. One thing though. in my actual code, the assignment to the multidimensional array is completely removed from its construction (in completely separate functions, in fact), so the lines couldn't be executed at once. Would this still cause the debugger to step out of the function where the assignment occurred?
As i said the debugger somehow executes "too much" for the assignment line. So it's possible that it executes the next few opcodes as well as it might think they belong to the same instruction / line of code. It's possible that this might be caused by the different compilers used. Unity compiles your assemblies using the $$anonymous$$ono C# compiler while VisualStudio relies on the .NET C# compiler.
Just try to place a breakpoint on the next line after the assignment and keep in $$anonymous$$d to not use Step over or Step into when executing the assignment.
Your answer
![](https://koobas.hobune.stream/wayback/20220612142651im_/https://answers.unity.com/themes/thub/images/avi.jpg)