Копирование массива C ++ в массив без знака - PullRequest
0 голосов
/ 02 апреля 2012

Я пытаюсь прочитать файл и сохранить информацию в беззнаковых массивах. Однако моя программа перезаписывает переменные.

Заголовок ClassA:

...
public:
    ClassA(void);
    void LoadMemoryBlock(char* block, int bank);
....
private:
    unsigned char upperMemoryBank1[16384];
    unsigned char upperMemoryBank2[16384];
....

Файл ClassA:

ClassA::ClassA(void)
{
}
...
void ClassA::LoadMemoryBlock(char* block, int bank)
{
    if (bank == 1)
    {
        memcpy(upperMemoryBank1, block, 16384);
    }
    else if (bank == 2)
    {
        memcpy(upperMemoryBank2, block, 16384);
    }
}

Заголовок ClassB:

...
private:
    ClassA* classAobject;
...

Файл ClassB:

ClassB::ClassB()
{
    classAobject = &ClassA();
    ...
}
...
ClassB::StoreFile(ifstream &file)
{
    int position;

    char fileData[16384];

    position = file.tellg();
    file.seekg(HEADER_SIZE, ios::beg);
    position = file.tellg();
    file.read(fileData, 16384);
    position = file.tellg();
    classAobject->LoadMemoryBlock(fileData, 1);
    classAobject->LoadMemoryBlock(fileData, 2);

    position = file.tellg(); // Crashes here
    file.seekg(16384 + HEADER_SIZE, ios::beg);
    ...
}

Просмотр переменной position в моем отладчике показывает, что после вызовов LoadMemoryBlock он больше не показывает 16400, как это было раньше, а скорее случайное число, которое каждый раз отличается. Кроме того, файл ifstream также поврежден вызовом LoadMemoryBlock. Поэтому я предполагаю, что memcpy перезаписывает их.

Я попытался инициализировать свои массивы по-другому, но теперь memcpy вылетает!

Заголовок ClassA:

...
public:
    ClassA(void);
    void LoadMemoryBlock(char* block, int bank);
....
private:
    unsigned char* upperMemoryBank1;
    unsigned char* upperMemoryBank2;
....

Файл ClassA:

ClassA::ClassA(void)
{
    upperMemoryBank1 = new unsigned char[16384];
    upperMemoryBank2 = new unsigned char[16384];
}
...
void ClassA::LoadMemoryBlock(char* block, int bank)
{
    if (bank == 1)
    {
        memcpy(upperMemoryBank1, block, 16384); // Crashes here
    }
    else if (bank == 2)
    {
        memcpy(upperMemoryBank2, block, 16384);
    }
}

Заголовок ClassB:

...
private:
    ClassA* classAobject;
...

Файл ClassB:

ClassB::ClassB()
{
    classAobject = &ClassA();
    ...
}
...
ClassB::StoreFile(ifstream &file)
{
    int position;

    char* fileData = new char[16384];

    position = file.tellg();
    file.seekg(HEADER_SIZE, ios::beg);
    position = file.tellg();
    file.read(fileData, 16384);
    position = file.tellg();
    classAobject->LoadMemoryBlock(fileData, 1);
    classAobject->LoadMemoryBlock(fileData, 2);

    position = file.tellg();
    file.seekg(16384 + HEADER_SIZE, ios::beg);
    ...
}

Я думал, что по крайней мере один, если не оба, эти методы должны работать. Что я делаю не так?

РЕДАКТИРОВАТЬ : Я включил инициализацию ClassA выше.

Вот как я вызываю метод StoreFile:

bool ClassB::Load(char* filename)
{
    ifstream file(filename, ios::in|ios::binary);

    if(file.is_open())
    {
        if(!StoreFile(file))
        {
            return false;
        }

        file.close();
        return true;
    }

    printf("Could not open file: %s\n", filename);
    return false;
}

Ответы [ 2 ]

2 голосов
/ 02 апреля 2012

99% вероятность ошибки в любом коде, инициализирующем значение указателя classAobject.Если он указывает на допустимый экземпляр объекта ClassA, код должен быть в порядке.

Обновление : Да.Вот и все.

classAobject = &ClassA();

Это создает новый объект ClassA и затем сохраняет указатель на него.Но в конце оператора он выходит из области видимости и уничтожается, оставляя classAobject с указателем на несуществующий объект.Вы хотите:

classAobject = new ClassA();

Не забывайте правило трех - delete в деструкторе, выделите новое в operator= и в конструкторе копирования.Или, что еще лучше, используйте метод C ++, такой как интеллектуальный указатель, в зависимости от желаемой семантики.

1 голос
/ 02 апреля 2012

В конструкторе ClassB вы инициализируете указатель classAobject на адрес временной переменной, которая становится недействительной, как только возвращается конструктор.Это причина проблемы.Используйте new для создания правильного объекта кучи.

...