Стоп вокруг переменной поврежден, не уверен, в чем проблема - PullRequest
2 голосов
/ 13 июня 2011

Проблема решена, спасибо всем за помощь

У меня есть небольшая проблема здесь, это не то, что взрывает мою программу, а просто беспокоит меня, что я не могу это исправить. У меня есть функция чтения некоторых данных из файла, в конце выполнения стек вокруг переменной longGarbage поврежден. Я немного осмотрелся и обнаружил, что возможной причиной является запись в недействительную память. Я устранил некоторые утечки памяти, которые у меня были, и проблема все еще сохраняется. Что меня смущает, так это то, что это происходит, когда функция завершает выполнение, поэтому это происходит, когда переменная выходит из области видимости. Вот код ...

CHCF::CHCF(std::string fileName)
: PAKID("HVST84838672")
{
FILE * archive = fopen(fileName.c_str(), "rb");
std::string strGarbage = "";
unsigned int intGarbage = 0;
unsigned long longGarbage = 0;
unsigned char * data = 0;
char charGarbage = '0';

if (!archive)
{
    fclose (archive);
    return;
}

for (int i = 0; i < 12; i++)
{
    fread(&charGarbage, 1, 1, archive);
    strGarbage += charGarbage;
}


if (strGarbage != PAKID)
{
    fclose(archive);
    throw "Incorrect archive format";
}
strGarbage = "";

fread(&_gameID, sizeof(_gameID),1,archive);
fread(&_fileCount, sizeof(_fileCount),1,archive);

for (int i = 0; i < _fileCount; i++)
{
    fread(&longGarbage, 8,1,archive); //file offset

    fread(&intGarbage, 4, 1, archive);//fileName

    for (int i = 0; i < intGarbage; i++)
    {
        fread(&charGarbage, 1, 1, archive);
        strGarbage += charGarbage;
    }

    fread(&longGarbage, 8, 1, archive); //fileSize

    fread(&intGarbage, 4, 1, archive); //fileType

    data = new unsigned char[longGarbage];

    for (long i = 0; i < longGarbage; i++)
    {
        fread(&charGarbage, 1, 1, archive);
        data[i] = charGarbage;
    }

    switch ((FILETYPES)intGarbage)
    {
    case MAP:
        _maps.append(strGarbage, new CFileData(strGarbage, FILETYPES::MAP, data, longGarbage));
        break;

    default:
        break;
    }

    delete [] data;
    data = 0;
    strGarbage.clear();
    longGarbage = 0;

}
fclose(archive);
} //error happens here

Вот конструктор CFileData:

CFileData::CFileData(std::string fileName, FILETYPES type, unsigned char *data, long fileSize)
{
_fileName = fileName;
_type = type;
_data = new unsigned char[fileSize];

for (int i = 0; i < fileSize; i++)
    _data[i] = data[i];
}

Ответы [ 4 ]

2 голосов
/ 13 июня 2011
  1. Могу ли я предложить std::vector вместо вызова new и удалить вручную?Ваш код не является безопасным для исключения - вы получаете утечку, если выдается исключение.

  2. fread(&longGarbage, 8, 1, archive); //fileSize Вы уверены, что sizeof(long) равно 8?Я подозреваю, что это 4. Я верю, что в Linux-системах иногда это 8, но в большинстве других случаев sizeof(long) - это 4, а sizeof(long long) - это 8.

  3. Как насчет любых конструкторов на членахэтот класс?Они также могут испортить стек.

1 голос
/ 13 июня 2011

Что происходит, так это то, что что-то записывается в память вокруг или над местоположением longGarbage, что вызывает повреждение.

Вы не говорите, какую среду разработки вы используете. Один из способов диагностики этого - установить точку останова, которая срабатывает при изменении определенной области памяти. Выберите область памяти, которая перекрывает область повреждения, и дождитесь ее неожиданного запуска.

Другим способом диагностики может быть проверка кода, который изменяет память вокруг или через longGarbage. Конечно, это может быть что угодно, но вероятными кандидатами являются модификации «данных», модификации «intGarbage» и модификации самой «longGarbage».

Мы можем еще более сузить ситуацию, поскольку можем (обычно) быть достаточно уверенными, что сам оператор присваивания безопасен. Код, подобный data = new..., вряд ли является виновником, поэтому на самом деле нам нужно сосредоточиться на изменениях памяти, которые включают в себя получение адреса «data», «intGarbage» или «longGarbage». В частности, изменения памяти, которые меняют больше байтов, чем должны.

Несколько других уже указали, что длина, вероятно, не восемь байтов в длину. Если вы передаете неправильную длину в fread, дополнительные извлеченные байты должны куда-то идти.

0 голосов
/ 14 июня 2011

Из других комментариев и предоставленной информации видно, что проблема на стороне C ++, вы должны использовать либо __int64 для среды Windows, либо int64_t для кроссплатформенности.

0 голосов
/ 13 июня 2011

Вы используете много магических чисел для размеров данных, поэтому я бы сначала проверил это.В частности, я сомневаюсь, что sizeof(unsigned long)==8 и sizeof(unsigned in)==4 при всех возможных обстоятельствах.Обратитесь к документации вашего компилятора, но вы все равно должны быть осторожны, поскольку это очень вероятно изменится с одного компилятора / платформы на другую.

Проверьте эти биты:

fread(&longGarbage, 8,1,archive); //file offset

Вы такжеВозможно, вы захотите использовать библиотеку C ++ <iostream> вместо содержимого C FILE* для чтения.Это позволило бы получить более короткую версию, потому что вам не нужно закрывать файл 3 раза.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...