Я компилирую, используя Code :: Blocks в Windows 7, используя компилятор MinGW (я могу только предположить, что это последняя версия; Code :: Blocks и MinGW были установлены на прошлой неделе).Моя проблема возникает при определенных обстоятельствах, и мои попытки написать более простой сценарий, который демонстрирует проблему, потерпели неудачу (что подразумевает, что с моей структурой что-то не так).Кроме того, я прошу прощения за то, как долго этот пост.
В настоящее время я работаю с одним классом, FXSDL, который будет действовать как оболочка SDL:
class FXSDL
{
public:
FXSDL();
virtual ~FXSDL();
int Initialize();
int Render();
FXID CreateCharacter(FXID hRefID, string fpImage, int wpxTile, int hpxTile, map<int, vector<int> > htAnims);
int SetAnim(FXID hRefID, FXID hAnimID);
FXID hPlayer;
protected:
private:
list<FXSurface> m_lstFXObjects;
list<FXSurface>::iterator m_liFirst;
SDL_Surface* m_lpsfSDLScreen;
Uint32 m_tmOld;
Uint32 m_tmFrame;
};
Тип значенияМой список:
struct FXSurface
{
FXID hRefID;
int wpxTile;
int hpxTile;
int wpxTotal;
int hpxTotal;
int cntTiles;
map<int, vector<int> > htAnims; // All animations
map<int, vector<int> >::iterator vCurr; // Currently active animation
vector<int>::iterator fiCurr; // Currently active frame
SDL_Surface* lpsfSDL;
SDL_Rect* lprcTiles; // Predefined frame positions
string* fpImage;
};
Я реализовал очень простую функцию инициализации и рендеринга.Функция CreateCharacter принимает несколько параметров, наиболее важным из которых является htAnims, карта целочисленных векторов (идея заключается в следующем: я определяю числовые идентификаторы с легко запоминаемыми представлениями, такими как FXA_IDLE или FXA_WALK, в качестве ключа, и сериючисловых значений, представляющих кадры для анимации как вектор).Это может быть довольно легко реализовано как многомерный целочисленный массив, но анимации имеют переменную длину, и я хочу иметь возможность добавлять новые анимации (или переопределять существующие) без необходимости переписывать массив.
Функция CreateCharacterэто просто.Он создает новый FXSurface, заполняет его необходимыми данными и помещает новый FXSurface в список:
FXID FXSDL::CreateCharacter(FXID hRefID, string fpImage, int wpxTile, int hpxTile, map<int, vector<int> > htAnims)
{
//list<FXSurface>::iterator lpsfTemp;
FXSurface lpsfTemp;
list<FXSurface>::iterator lpsfPos;
SDL_Rect* lprcCurr = NULL;
int cntTileW = 0;
int cntTileH = 0;
int cntCurr = 0;
// Start off by initializing our container struct
//lpsfTemp = new FXSurface();
lpsfTemp.lpsfSDL = IMG_Load(fpImage.c_str()); // Try to load the requested image
if(lpsfTemp.lpsfSDL != NULL) // If we didn't fail to
{
// Assign some variables for tracking
lpsfTemp.hRefID = hRefID;
lpsfTemp.fpImage = &fpImage;
lpsfTemp.wpxTotal = lpsfTemp.lpsfSDL->w;
lpsfTemp.hpxTotal = lpsfTemp.lpsfSDL->h;
// If a tile width was specified, use it
if(wpxTile != 0)
{
lpsfTemp.wpxTile = wpxTile;
lpsfTemp.hpxTile = hpxTile;
} // Otherwise, assume one tile
else
{
lpsfTemp.wpxTile = lpsfTemp.wpxTotal;
lpsfTemp.hpxTile = lpsfTemp.hpxTotal;
}
// Determine the tiles per row and column for later
cntTileW = lpsfTemp.wpxTotal / lpsfTemp.wpxTile;
cntTileH = lpsfTemp.hpxTotal / lpsfTemp.hpxTile;
// And the total number of tiles
lpsfTemp.cntTiles = cntTileW * cntTileH;
lpsfTemp.lprcTiles = new SDL_Rect[cntTileW*cntTileH];
// So we don't calculate this every time, determine each frame's coordinates and store them
for(int h = 0; h < cntTileH; h++)
{
for(int w = 0; w < cntTileW; w++)
{
cntCurr = (h*cntTileW)+w;
lprcCurr = new SDL_Rect;
lprcCurr->w = lpsfTemp.wpxTile;
lprcCurr->h = lpsfTemp.hpxTile;
lprcCurr->x = w*lpsfTemp.wpxTile;
lprcCurr->y = h*lpsfTemp.hpxTile;
lpsfTemp.lprcTiles[cntCurr] = *lprcCurr;
lprcCurr = NULL;
}
}
// Now acquire our list of animations and set the default
//lpsfTemp.htAnims = new map<int, vector<int> >(*htAnims);
lpsfTemp.htAnims = htAnims;
lpsfTemp.vCurr = lpsfTemp.htAnims.find(FXA_WALK_EAST);
lpsfTemp.fiCurr = lpsfTemp.vCurr->second.begin();
this->m_lstFXObjects.push_back(lpsfTemp);
}
else
{
hRefID = 0;
}
return hRefID;
}
Именно при нажатии объекта происходит ошибка.Я прошел через код много раз.Изначально я мог только сказать, что мои итераторы не могли разыменовать объект FXSurface.После использования часов для определения точного адреса памяти, на который указали объекты итератора и списка, и разыменования адреса, я заметил причину моих ошибок: все значения, которые я поместил в исходный FXSurface, были сдвинуты вниз на два блока памяти, когда списокобъект скопировал его!
Мой процесс для этого прост.Я установил точку останова в операторе возврата для CreateCharacter, который дает мне представление о lpsfTemp (FXSurface, который я позже добавлю в список) и m_lstFXObjects (список, к которому я добавляю его).Я прокручиваю элементы m_lstFXObjects, что приводит меня к _M_node, который содержит адрес памяти единственного объекта, который я добавил до сих пор.Я добавляю часы по этому адресу в виде (FXSurface ) - шестнадцатеричный адрес здесь -
Сначала найдите адрес:
(здесь должна быть картинкапоказывает выделенный атрибут _M_node, содержащий адрес элемента списка, но я не могу публиковать изображения, и я могу публиковать только один URL. Второй гораздо важнее. Он расположен по адресу http://www.fauxsoup.net/so/address.jpg)
Далее,мы приводим и преобразуем адрес. Это изображение показывает и lpsfTemp, и копию в m_lstFXObjects; обратите внимание на несоответствие?
http://www.fauxsoup.net/so/dereferenced.jpg - Видите? Все значения в правильном порядке, просто смещены на двасписки
Первоначально я хранил fpImages как char *, поэтому я подумал, что это могло сбить с толку, но теперь это всего лишь указатель, и проблема сохраняется. Возможно, это связано с картойЯ храню?