Vyra Vyra - 1 month ago 7
C# Question

Different value for same element in ByteArray?

Why am I getting byte 0x00 at index 0 instead of 0xD0 when calling the SetData() method from outside the class?

Here's a shortened down of the class:

using System;

namespace StackOverflow
{
class Section
{
uint _sectionId;
byte[] _sectionData;

public Section(byte[] sectionData) {
_sectionData = sectionData;
_sectionId = GetUShort(0x0FF4);
Console.WriteLine(_sectionId + ": " + _sectionData[0].ToString("X")); // Gives D0
}

public void SetData() {
switch (_sectionId) {
case 0: SetTrainerInfo(); break;
default: break;
}
}

void SetTrainerInfo() {
Console.WriteLine(_sectionId + ": " + _sectionData[0].ToString("X")); // Can Give 0

byte[] deByte = GetBytes(0x00, 7);

TrainerInfo.playerName = PkmString.GetString(deByte);
Console.WriteLine(TrainerInfo.playerName + "name here");
}
}
}


Works fine if called in the Section constructor, but not from an external source like this:

using System;

namespace StackOverflow
{
class SaveBlock
{
const short SECTIONS = 14, SECTION_SIZE = 4096;

public Section[] sections = new Section[SECTIONS];

public SaveBlock(byte[] blockData) {
byte[] sectionData = new byte[SECTION_SIZE];
for (int i = 0; i < SECTIONS; i++) {
Array.Copy(blockData, SECTION_SIZE * i, sectionData, 0, SECTION_SIZE);
sections[i] = new Section(sectionData);
}
}

public void SetForAll() {
foreach (Section sect in sections)
sect.SetData();
}
}
}


And I get different bytes for the same element:
Same byte is different

Answer

Look at this code from the SaveBlock constructor:

byte[] sectionData = new byte[SECTION_SIZE];
for (int i = 0; i < SECTIONS; i++) {
    Array.Copy(blockData, SECTION_SIZE * i, sectionData, 0, SECTION_SIZE);
    sections[i] = new Section(sectionData);
}

The loop copies the blockData bytes to the sectionData array, and then uses sectionData to create a new Section object instance. Here's where things get tricky... arrays are reference types. That means the following line in your Section constructor is only copying the reference to the array:

_sectionData = sectionData;

As you move through the loop, you're copying data into the same array instance over and over, and then assigning that same array instance to the internal data of several Section objects. All of those objects are sharing the same array instance! It's very likely you want a new array for each of those objects:

byte[] sectionData;
for (int i = 0; i < SECTIONS; i++) {
    sectionData = new byte[SECTION_SIZE];
    Array.Copy(blockData, SECTION_SIZE * i, sectionData, 0, SECTION_SIZE);
    sections[i] = new Section(sectionData);
}

That may not be the only problem, as _sectionId is shown defined private an initialized to non-0. The SetData() method looks like this:

public void SetData() {
    switch (_sectionId) {
        case 0: SetTrainerInfo(); break;
        default: break;
    }
}

From the code we can see, there is no way that _sectionId will ever be 0, and thus no way that SetTrainerInfo() is ever called.