2009-07-27 6 views
2

Я наткнулся на странную проблему, в которой я не могу понять. Я не эксперт на C/C++, так что несите меня. У меня есть класс NPC, который происходит из класса Player, который происходит из класса Sprite. Класс спрайтов содержит функцию setupAnimation, которая выделяет массив поплавков, содержащих координаты на текстуре, каждый элемент массива относится к кадру анимации. Это все хорошо и прекрасно работает.Ошибка распределения памяти

Однако проблема возникает, когда я добавляю массив указателей в класс NPC. Эти указатели имеют тип класса Item. Когда я добавляю этот массив, он отлично работает, если массив мал (10 был размером, который я тестировал), но будет сбой при распределении массива поплавков для координат текстуры, упомянутых ранее, если размер немного больше (100 был размером I испытано).

Вот некоторые фрагменты кода, показывающие материал я уже упоминал выше:

пункт, класс массив указателей:

engItem* itsLoot[100]; // With 100 here, the crash occurs as shown below 

координаты текстуры и их распределение двойники:

GLfloat* itsTextureXData; 
    GLfloat* itsTextureYData; 

    ... 

    animationFile >> frameCount; // Tested, the value is correct 

    engDeallocate(getTextureXData(), true); // Works fine 
    itsTextureXData = new GLfloat[frameCount]; // This is where the crash occurs 

    engDeallocate(getTextureYData(), true); 
    itsTextureYData = new GLfloat[frameCount]; 

Это фрагмент кода является основой каждого класса, который происходит из класса Sprite. Я не понимаю, почему дополнительные 90 указателей вызывают проблему во время размещения поплавка. Просто немного информации о программном обеспечении, чтобы пойти с этим

ОС: Windows Vista 32-битной, компилятор: Visual C++ 9.0, среда Программа памяти: ~ 17,600k, Системная память: ~ 2GB

Имея это в виду, Я не могу видеть, что память работает сухая, и я не могу связать, как массив указателей приводит к сбою распределения. Как уже упоминалось, распределение работает отлично во всех других классах, полученных из Sprite (а также с помощью Sprite), но как только этот массив указателей добавлен в класс NPC, NPC больше не будет распределять этот массив массивов данных текстур без сбоев.

+0

Что такое крах? То есть, что такое callstack и код исключения или assert, если они доступны? – MSN

ответ

3

Симптомы, которые вы описываете, типичны для системы с поврежденным распределением памяти. Тот факт, что ошибка возникает, когда вы говорите, что она, вероятно, не имеет значения - реальная ошибка почти наверняка находится в другом месте.

Существует множество способов уменьшить шансы на это, но главный - написать код на C++, а не C с небольшим синтаксисом C++. Используйте коллекции, такие как std :: vector, которые выполняют собственное управление памятью, а не пытаются сделать это сами.

6

Где-то в вашей программе у вас, вероятно, есть какая-то ошибка памяти (написано в конце массива, написано в освобожденную память и т. Д.). Когда это произойдет, возможно, что вы можете перезаписать структуры, используемые системой распределения памяти, в результате чего он будет сбой при следующем распределении. Это может помочь запустить вашу программу с помощью инструмента, такого как Valgrind, чтобы найти, где ошибка. EDIT: Я просто понял, что вы используете Windows, а Valgrind работает только с Linux. Если ваш код достаточно портативен, было бы относительно легко попробовать Linux и Valgrind. Если вы не можете этого сделать, см. Is there a good Valgrind substitute for windows? на SO. (К сожалению, похоже, что большинство из них являются коммерческими, а не бесплатными и с открытым исходным кодом, такие как Valgrind.)

Лучший способ избежать этого - использовать коллекции C++, такие как std::vector или std::list, а не массивы. Если вы используете эти коллекции, убедитесь, что вы скопируете их до минимума (например, используйте ссылки const как параметры, а не копии исходного объекта, если вы его не модифицируете и т. Д.), или вы получите очень плохую производительность (и похоже, что вы делаете игру, поэтому это важно).

+1

Благодарим вас за быстрый ответ. Я уже упоминаю как можно больше. Я буду использовать вектор чаще, но я всегда нахмурился над библиотеками, которые делают то, что я могу сделать сам, поскольку они настроены так, как мне не нравится. Это основа плохого программиста, которого я знаю, и я, скорее всего, вырасту из него. Еще раз спасибо, очень признателен (а также спасибо Нилу выше). – 2009-07-27 14:02:54

+1

Я бы начал это изменение сейчас. Повторное изобретательство колеса ужасно. Как насчет их настройки, как вам нравится? – GManNickG

0

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

Чтобы сузить место, где находится настоящая ошибка, запустите в режиме отладки и попытайтесь увеличить частоту, с которой ЭЛТ проверяет кучу на наличие повреждений.

Следующий код взят из MSDN показывает, как позволить чеке CRT каждые 16 кучи операций вместо каждого 1024:

#include <crtdbg.h> 
int main() 
{ 
int tmp; 

// Get the current bits 
tmp = _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG); 

// Clear the upper 16 bits and OR in the desired freqency 
tmp = (tmp & 0x0000FFFF) | _CRTDBG_CHECK_EVERY_16_DF; 

// Set the new bits 
_CrtSetDbgFlag(tmp); 
} 

Для получения дополнительной информации см _CrtSetDbgFlag in MSDN