Some background:
I am using Box2D in a game I'm making. It has a way of storing "user-data" to Box2D objects. This "user-data" takes a void*, so that it can be used for storing user-defined data. Now, when Box2D collisions happen, you can use this "user-data" to identify which objects have collided. Then you can cast the data to a class, and access the functions or variables of that class (and the particular instance of that class, if you have set the "user-data" as a reference to that instance). I have two sets of "user-data", one is a reference to a class instance and another to a struct so I can check the type of the objects.
This works good for objects that are not in a vector. I have tested this, and I can access the functions and variables(and modify them) of class instances without them being reset. But when I access my std::vector< Tile> objects by casting from void*, the variables I modify get reset immediately.
Relevant code:
I set the "user-data" like this:
tile->SetUserData(static_cast<Entity*>(this));
ball->SetUserData(static_cast<Entity*>(this));
bUserData* bud = new bUserData;
bud->entityType = BALL;
ballFixture.userData = bud;
bUserData* bud = new bUserData;
bud->entityType = TILE;
tileFixture.userData = bud;
MyContactListener class keeps track when the collisions start and end, this is also where the casting from void* to foo* happens:
MyContactListener.cpp
std::vector<Tile> solidTiles;
Ball ball;
// Called when two objects begin to touch.
void MyContactListener::BeginContact(b2Contact* contact) {
// Cast from void* to a struct, from which I can check the object type.
bUserData* budA = (bUserData*)contact->GetFixtureA()->GetUserData();
bUserData* budB = (bUserData*)contact->GetFixtureB()->GetUserData();
// Cast from void* UserData to Entity* (super-class of all the entities).
Entity* entityA = (Entity*)contact->GetFixtureA()->GetBody()->GetUserData();
Entity* entityB = (Entity*)contact->GetFixtureB()->GetBody()->GetUserData();
if((budA->entityType == TILE && budB->entityType == BALL)) {
Tile* tile = (Tile*)entityA; // Tiles are in std::vector<Tile>
Ball* ball = (Ball*)entityB; // Only one ball instance exists
// Modifying a tile instance variable, gets reset to the original value immediately!
tile->flaggedToErase = true;
// This works fine!
ball->setColorToBlue = true;
}
}
Question: How do I keep variables of the tile instances in vector from being reset to their original value?
Is it supposed to be a vector of Tile or Tile*? At a guess, I would suspect that this problem is due to using vector<Tile> which stores a copy of the object, as opposed to vector<Tile*> which stores a pointer to the object.
Compare this:
std::vector< Tile > tiles;
Tile t;
t.foo = 123;
tiles.push_back( t ); // a copy of t is put into the vector
t.foo = 456; // changes t, but not the copy in the vector
Tile t2 = tiles[0]; // makes yet another copy (t2.foo == 123)
... with this:
std::vector< Tile* > tiles;
Tile* t = new Tile;
t->foo = 123;
tiles.push_back( t ); // a pointer is put into the vector
t->foo = 456; // also changes in the vector because it's the same thing
Tile* t2 = tiles[0]; // still the same thing (t2->foo == 456)
If you want to have a vector of objects (not pointers) and change them inside the vector, you can do it like this:
std::vector< Tile > tiles;
Tile& t = tiles[0]; // note the ampersand, accesses by reference
t.foo = 456; // changes inside the vector
// I think you can also do this
tiles[0].foo = 456;
However, to do this you need to have the vector itself available, and you need to know which position the element you want to change is at. For your case, you don't know which position the element is at within the vector, so using vector<Tile*> is the simplest solution.
Related
So I am trying to make a game in c++ with SDL2 and ran into a little problem. In order to pick up a weapon from the ground, after I check if the player is next to the object and has clicked 'E' to pick it up in an inline function from a different namespace, I have to copy its address in a variable saved in the main class and delete the object from the ground so you can't re-pick it up. It seems that after I delete the object, the pointer from the main class gets the value from another object, not that I erased.
This is the main class .h file:
class GameScene : public Scene{
public:
GameScene();
void init(SDL_Renderer* &renderer, int sceneIdx); //initialize variables
void update(int &sceneIdx, double deltaTime, Vector2f screenSize); //update frame-by-frame
void graphics(SDL_Renderer* &renderer); //render objects
void clear(); //only called on exit
private:
std::vector<SDL_Texture*> textures = {}; //all the textures present in the game
std::vector<bool> movements{false, false, false, false}; //main character movements
std::vector<Weapon> droppedWeapons = {}; //dropped pickable weapons on the ground
std::vector<Weapon*> weapons = {nullptr, nullptr}; //slots for the primary and secondary weapon
std::vector<Bullet> bullets = {}; //ssaves all the fired bullets on the map until deletion
std::unordered_map<int, SDL_Rect> positionsAtlas = {}; //offsets in textures and render scales
Cube* cube = nullptr; //main character
int mode = 0; //0=nothing, 1=weapon --unused yet
bool currentWeapon = 0; //saves what weapon is being used(primary or secondary)
int mouseX, mouseY; //mouse position on screen
};
Here is the function call in the .cpp file:
WeaponActions::pickUpWeapons(cube, droppedWeapons, weapons, pickUp/*is E pressed*/, currentWeapon);
And the function in the WeaponActions namespace:
inline void pickUpWeapons(Cube* cube, std::vector<Weapon> &droppedWeapons, std::vector<Weapon*> &weapons, bool pickUp, bool ¤tWeapon)
{
for(unsigned int i=0;i<droppedWeapons.size();i++)
{
bool type = droppedWeapons[i].getType(); //type of weapon(primary or secondary)
if(weapons[type]==nullptr && pickUp) //there is empty space in inventory
{
if(Math::checkCollision(cube->getPos(), cube->getScale(), droppedWeapons[i].getPos(), droppedWeapons[i].getScale())) //check if cube is near weapon
{
weapons[type] = &droppedWeapons.at(i); //save address
droppedWeapons.erase(droppedWeapons.begin()+i); //delete element
currentWeapon = currentWeapon == type ? currentWeapon : type; //change current weapon if necessary
i--;
}
}
}
}
The type element in the Weapon object represent if it is a primary(rifle) or a secondary(pistol) weapon.
What should I do beside creating another object to store the object the pointer is headed to?
Looks like you've got some confusion with memory and what should be a pointer. I'm looking specifically at how you store your weapons here:
std::vector<Weapon> droppedWeapons = {}; //dropped pickable weapons on the ground
std::vector<Weapon*> weapons = {nullptr, nullptr}; //slots for the primary and secondary weapon
When you pickup a weapon you are currently assigning the pointer to the memory location of the Weapon object in your vector, but then immediately removing that weapon! That's why you observed that it appears you equipped the wrong weapon. The weapon you picked up has gone, the std::vector has been resized and the next one has shunted down to fill it's place (std::vectors are required to be hold their elements in contiguous memory). This operation could also leave a dangling pointer e.g. if the weapon you tried to pick up was the last in the droppedWeapons vector your weapons pointer would end up pointing past the end of the vector.
Without changing too much of the rest of your code, you could change droppedWeapons to a vector of Weapon* (weapon pointers), rather than Weapon. Then when you want to pickup the weapon, assign the pointer to your picked up weapons list like so:
weapons[type] = droppedWeapons.at(i); // pass weapon pointer
Followed by removing the element from droppedWeapons as you are already.
Now you are working with pointers you will have to fill droppedWeapons by allocating them with new, and cleanup all your Weapon* at some point with delete.
Before making this change, it may also be a good idea to learn more about stack vs heap memory allocation in c++ if you aren't familiar with it already :)
class tile :public RectangleShape
{
public:
int w;
int t1rgb1;
int t1rgb2;
int t1rgb3;
int t2rgb1;
int t2rgb2;
int t2rgb3;
void modify(int,int,int,int,int,int,int);
};
I have a tile class that inherits RectangleShape. I've made a 2d Vector of this class and want to push_back Rectangle shapes into it from a method of another class. I know my code won't work because I don't know where my RectangleShape will be push_back'ed into, x or y.
board::create(int x, int y){
cBoard = vector <vector <tile> >(x, vector< tile >(y, tile()));
int counter = 0;
RectangleShape t;
for(int i = 0; i < y; i++){
counter = 0;
if(i % 2 == 1){
counter = 1;
}
for(int ii = 0; ii < x; ii++){
if(counter % 2 == 0){
t.setFillColor(Color::Red);
cBoard.push_back(t);
cout << "red";
counter++;
}
else if(counter % 2 == 1){
t.setFillColor(Color::Green);
cBoard.push_back(t);
cout << "green";
counter++;
}
}
cout << endl;
}
}
The short answer is that you can't. Changing it to a 1D vector won't help either.
If you want to combine a container with inheritance, you almost certainly need the container to store some sort of pointer-like or reference-like thing, rather than storing the objects directly.
Depending on the situation, those might be std::unique_ptr, or std::reference_wrapper, or possibly just raw pointers in something like a Boost ptr_vector. One way or another, however, if you're using inheritance, you just about need to deal with the objects via something pointer-like or something reference-like rather than working directly with objects themselves.
The way to do this kind of thing is using dynamic_cast and store pointers, rather than values. For example:
RectangleShape r1 = new RectangleShape();
RectangleShape r2 = new tile();
tile* t1 = dynamic_cast<tile>(r1);
tile* t2 = dynamic_cast<tile>(r2);
In the above code snippet, t1 will be nullptr, because r1 is not a tile object. t2 will point to the correct tile object. Storing the pointers in a vector should probably be done with unique_ptr to prevent memory management issues.
If this is not what you want to do, if you want to actually create a tile object out of a RectangleShape object, then you would need to give the tile class a constructor that takes a RectangleShape object (preferably explicit), or create a function that takes a RectangleShape object and returns a tile object.
Finally, make sure when you're doing this that RectangleShape is actually the kind of object you would want to derive another class from. It must have a virtual destructor, and any overriden methods should also be virtual.
So I am new to C++ and I am trying to use an inner class like this:
struct PreviousButton {
SelectionScreen* ss;
PreviousButton(SelectionScreen* sss) {
ss = sss;
}
void ClickAction() {
//images is a vector with images. in here it is empty
ss->images;
}
};
This inner class is inside the class SelectionScreen and I need to perform a click action and need some of the variables of the selectionscreen.
SelectionScreen:
class SelectionScreen {
public:
void AddImage(Image img);
std::vector<Image> images;
How I fill the vector:
Image* image = new Image{ };
AddImage(*image2);
AddImage method:
void SelectionScreen::AddImage(Image img)
{
images.push_back(img);
}
But when I try to use the selectionscreen inside the class all of the variables are empty. But when I look into selectionscreen all of the variables are set.
The way I pass the SelectionScreen:
PreviousButton* previousButton = new PreviousButton(*ren, this);
How SelectionScreen gets initialized: (this method is called from the main)
int Program::Render() {
bool quit = false;
MenuScreen m = SelectionScreen{ Sdl_Renderer };
// change current screen to selectionscreen
ScreenController::GetInstance().ChangeMenu(m);
while (!quit) {
// handle user input and repaint
}
// delete all windows if quit is true
SDL_DestroyRenderer(Sdl_Renderer);
SDL_DestroyWindow(Sdl_Window);
SDL_Quit();
return 0;
}
Does anyone knows why my variables are empty?
This isn't addressing the immediate issue you describe, but you have a serious problem here:
ss->currentImageIndex = ss->images.capacity() - 1;
images.capacity() - 1 is not guaranteed to return a valid index into your vector. You should use images.size() - 1.
std::vector::capacity() tells you the storage space currently allocated for the vector, not the number of elements it actually contains.
UPDATE
When you assign a SelectionScreen to a MenuScreen like this
MenuScreen m = SelectionScreen{ Sdl_Renderer };
you "slice" the SelectionScreen object (see What is object slicing?).
This line creates a new MenuScreen object, m, by copy-constructing it from a temporary SelectionScreen object. The new MenuScreen object, m, is not a SelectionScreen. It is also a completely distinct object from the temporary SelectionScreen created on the right-hand side of this expression.
Your PreviousButton, which I assume is created in the constructor of SelectionScreen, holds a pointer to the temporary SelectionScreen, which the compiler is free to delete once this line has completed.
To fix this, you could use this initialisation instead:
MenuScreen& m = SelectionScreen{ Sdl_Renderer };
In this case, m is a reference to your (temporary) SelectionScreen - this is good because (a) references are polymorphic, so it still knows that it's really a SelectionScreen, not just a MenuScreen and (b) it's a reference to the exact same SelectionScreen object created on the right-hand side, which your PreviousButton has a pointer to. I've also bracketed the "temporary" bit now, because taking a local reference to a temporary guarantees it will exist for as long as the reference does (see e.g. Does a const reference prolong the life of a temporary?).
Note that I am assuming here that you only make use of this SelectionScreen within the while (!quit) loop that follows, i.e. the screen can safely be deleted at the end of this int Program::Render() method.
I am converting some code between different systems, and I have a question regarding c++ vectors.
If I do something like this:
In header file:
struct Vertex
{
float x;
float y;
float z;
}
struct submesh
{
Vertex *meshdata;
}
std::vector<submesh> meshes;
In a routine in the c++ file:
{
Vertex *data = new Vertex[1024];
submesh g;
g.meshdata = data;
meshes.push_back(g);
delete [] data;
}
Will I be in trouble? My assumption is that the vector would hold a pointer to data that is no longer valid once I called delete on it. Do I need to write a copy constructor for Vertex so that the data is copied first?
Additional:
The question was more to do with how do I put a pointer to allocated memory into a std::vector<> and still cleanup the locally allocated data. Essentially, how do I copy the data into the vector so I can still clean up my copy.
The original code was in DirectX. I am porting it to the iPhone. The original code allocated a submesh locally in a routine using:
{
ID3DXMesh* subMesh = 0;
D3DXCreateMesh(SubGrid::NUM_TRIS, SubGrid::NUM_VERTS, D3DXMESH_MANAGED, elems, gd3dDevice, &subMesh));
//
// ... do some magical things to submesh
//
SubGrid g;
g.mesh = subMesh;
g.box = bndBox;
mSubGrids.push_back(g);
}
I am trying to duplicate how ID3DXMesh is able to be added to a vector, then lose it's scope in the routine.
As I don't have access to D3DXCreateMesh(), I figured I would simply allocate the vertices I needed, throw them into a vector, and clean up.
Sorry, I wanted to keep the nitty gritty details out of it, as the question is simply how do I allocate a chunk of data, put a pointer into a std::vector<>, then clean up the locally allocated memory. :)
I assumed a copy constructor had to be written somewhere. Just wasn't sure where or how.
A subgrid looks like this:
struct SubGrid
{
ID3DXMesh* mesh;
AABB box;
// For sorting.
bool operator<(const SubGrid& rhs)const;
const static int NUM_ROWS = 33;
const static int NUM_COLS = 33;
const static int NUM_TRIS = (NUM_ROWS-1)*(NUM_COLS-1)*2;
const static int NUM_VERTS = NUM_ROWS*NUM_COLS;
};
And the vector they get added to looks like:
std::vector<SubGrid> mSubGrids;
Don't directly dynamicly-allocate when you don't need to, and in this case you don't. Since you're filling your own submesh data rather than using ID3DXMesh, the container of that data should be RAII-compliant. If I were coding this I would remove the submesh class entirely and just use:
// vector containing list of vertices.
typedef std::vector<Vertex> SubMesh;
Your SubGrid class can then become a simple container that holds, as one of its properties, a submesh collection. I noticed you also have a class AABB for a box object. You would continue to keep that inside SubGrid. I don't have ton to work with here, so I'm making some of these up as I go along, but something like the following:
// a simple 3-value triplet of floats
struct Vertex
{
float x,y,z;
};
// a Submesh is an arbitrary collection of Vertex objects.
typedef std::vector<Vertex> SubMesh;
// I'm defining AABB to be an 8-vertex object. your definition
// is likely different, but I needed something to compile with =)
typedef Vertex AABB[8];
class SubGrid
{
public:
SubGrid() {};
// comparator for container ordering
bool operator <(const SubGrid&);
// submesh accessors
void setSubmesh(const SubMesh& mesh) { submesh = mesh;}
SubMesh& getSubmesh() { return submesh; }
const SubMesh& getSubmesh() const { return submesh; }
// box accessors
AABB& getBox() { return box; }
const AABB& getBox() const { return box;}
private:
SubMesh submesh;
AABB box;
};
// arbitrary collection of SubGrid objects
typedef std::vector<SubGrid> SubGrids;
When adding this to your global SubGrid collection g, you have several possibilities. You could just do this:
// declared globally
Subgrids g;
// in some function for adding a subgrid item
SubGrid subgrid;
AABB& box = subgrid.getBox();
SubBesh& submesh = subgrid.getSubmesh();
// ... initialize your box and submesh data ...
g.push_back(subgrid);
But you'd be copying a lot of data around. To tighten up the memory access you could always do this instead:
// push an empty SubGrid first, then set it up in-place
g.push_back(SubGrid());
Subgrid& subgrid = *(g.back());
AABB& box = subgrid.getBox();
SubMesh& submesh = subgrid.getSubmesh();
//... initialize your box and submesh data ...
This will establish a reference to the SubGrid just added to the global collection, then allow you to modify it in-place. This is but-one of a number of possible setup options. It should be noted that if you have C++11 in your toolchain (and if you're doing this on MacOS or iOS, you likely do, as Apple LLVM 4.2's clang is pretty good on C++11 compliance) this can get even more efficient with judicious usage of move-constructors and move-assignment-operators.
Most importantly, not a new or delete to be seen.
Anyway, I hope this gives you some ideas.
Your code looks fine in single threaded application. Your code only allocate data memory once and delete [] data once.
Do I need to write a copy constructor for Vertex so that the data is copied first?
Your code is clean as you shown, meshes points to only allocated data. If you meant to copy data when call meshes.push_back(g), then your code doesn't do what you meant to.
You might want to use std::vector instead:
struct submesh
{
std::vector<Vertex> meshdata;
}
vector<submesh> meshes;
void Func()
{
meshes.emplace_back(submesh());
meshes.at(0).meshdata.resize(100);
}
STL container uses RAII idiom, it manages memory deallocation for you automatically.
Yes of course, vector will have a pointer to deleted memory. What you need is either:
Create copy constructor for submesh (not Vertex).OR
Changesubmesh to have array of Vertex (not just a pointer).
Copy constructor can be done like this:
struct submesh
{
Vertex *meshdata;
unsigned meshsize;
submesh(Vertex* v = 0, unsigned s= 0) : meshdata(v), meshsize(s){}
submesh(const submesh& s)
{
if(meshdata) /*we have stored data, delete it.*/ delete(meshdata);
meshdata = new Vertex[s.meshsize];
meshsize = s.meshsize;
memcpy(meshdata, s.meshdata, sizeof(Vertex) * meshsize);
}
};
For sure it is much recommended to use unique_ptr (if you use c++11) or auto_ptr for old c++. To avoid the nightmare of memory management as much as you can.
Check How to avoid memory leaks when using a vector of pointers to dynamically allocated objects in C++?
I'm compiling using Code::Blocks on Windows 7 using the MinGW compiler (which I can only assume is the latest version; both Code::Blocks and MinGW were installed this past week). My issue crops up under a particular circumstance, and my attempts to write a simpler script that demonstrates the problem have failed (which implies that there is something wrong with my structure). Also, my apologies for how long this post is.
Currently, I'm rolling with one class, FXSDL, which will act as an SDL wrapper:
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;
};
The value type of my list is:
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;
};
I've implemented very simple initialize and render function. The CreateCharacter function takes a few parameters, the most important of which is htAnims, a map of integer vectors (idea being: I define numeric ids with easy-to-remember representations, such as FXA_IDLE or FXA_WALK, as the key, and the series of number values representing frames for the animation as a vector). This could be fairly easily implemented as a multidimensional integer array, but animations are variable in length and I want to be able to add new anims (or redefine existing ones) without having to recast an array.
The CreateCharacter function is simple. It creates a new FXSurface, populates it with the required data, and pushes the new FXSurface onto the list:
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;
}
It is precisely as the object is pushed that the error occurs. I've stepped through the code numerous times. Initially, I was only able to tell that my iterators were unable to dereference to the FXSurface object. After using watches to identify the exact memory address that the iterator and list objects pointed to, and dereferencing the address, I noticed the reason for my segfaults: all the values which I put into the original FXSurface were pushed down two memory blocks when the list object copied it!
My process for doing this is simple. I set up a breakpoint at the return statement for CreateCharacter, which gives me a view of lpsfTemp (the FXSurface I later add to the list) and m_lstFXObjects (the list I add it to). I scroll through the members of m_lstFXObjects, which brings me to _M_node, which contains the memory address of the only object I have added so far. I add a watch to this address in the form of (FXSurface)-hex address here-
First, find the address:
(There should be a picture here showing the highlighted _M_node attribute containing the list item's address, but I can't post pictures, and I can only post one URL. The second one is by far more important. It's located at http://www.fauxsoup.net/so/address.jpg)
Next, we cast and deference the address. This image shows both lpsfTemp and the copy in m_lstFXObjects; notice the discrepancy?
http://www.fauxsoup.net/so/dereferenced.jpg - See? All the values are in the correct order, just offset by two listings
I had initially been storing fpImages as a char*, so I thought that may have been throwing things off, but now it's just a pointer and the problem persists. Perhaps this is due to the map<int, vector<int> > I store?
FXSDL has a destructor, but no copy constructor and no assignment operator. Yo you're using naked pointers, but violate the Rule of Three.
I'm not going to look any further.
Use smart pointers to manage resources. Do not put a naked resource into a type, except when that type's only intention is to manage this one resource. From another answer given yesterday:
As a rule of thumb: If you have to manually manage resources, wrap each into its own object.
At a glance, I'd say you're double-deleting lpsfSDL and/or lprcTiles. When you have raw pointers in your structure, you need to follow the rule-of-three (implement copy constructor, assignment operator, and destructor) to properly manage the memory.
These lines look wrong to me:
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;
lpsfTemp.lprcTiles is a SDL_Rect*. lprcTemp.lprcTiles[cntCurr] is a SDL_Rect. You should be writing this, IMHO:
SDL_Rect tmpRect;
tmpRect.w = lpsfTemp.wpxTile;
tmpRect.h = lpsfTemp.hpxTile;
tmpRect.x = w*lpsfTemp.wpxTile;
tmpRect.y = h*lpsfTemp.hpxTile;
lpsfTemp.lprcTiles[cntCurr] = tmpRect;
Dump the lprcCurr entirely.
Now this code:
lpsfTemp.vCurr = lpsfTemp.htAnims.find(FXA_WALK_EAST);
lpsfTemp.fiCurr = lpsfTemp.vCurr->second.begin();
This is bad. These iterators are invalid as soon as the push_back completes. That push_back is making a copy of lpsfTemp. The map and vector members are going to copy themselves and those iterators will copy themselves but they will be pointing to lpsfTemp's members which are going to be destroyed as soon as CreateCharacter exits.
One way to fix that would be to push_back a FXSurface object at the beginning, use back() to get its reference and operate on that instead of lpsfTemp. Then the iterators would stay consistent and they should stay consistent since you are using a list which does not copy its objects around. If you were using a vector or deque or anything other than a list you would need to manage all those pointers and iterators in the copy constructor and assignment operator.
Another thing: Double and triple check your array bounds when you access that lprcTiles array. Any mistake there and you could be scribbling over who knows what.
I don't know if any of that will help you.