Attempting to reference a deleted function (No reference to a funciton made) - c++

I'm experiencing a problem at the moment where apparently I am Attempting to reference a deleted function. As far as I can see, I'm not actually referencing a function but a smart pointer to a struct.
This is a university project whereupon multiple header files and CPP files are being used to allow us to understand how to use multiple files in the same project and link them together along with understanding and making use of polymorphism. We are using multiple files as the brief states we must. The files and definitions were provided for us.
The following is supposed to conduct a "Breadth-first" search on a terrain map (array of numbers ranging from 0-3) from a starting location to the goal location. It is about path-finding.
This is what I have so far:
#include "SearchBreadthfirst.h" // Declaration of this class
#include <iostream>
#include <list>
using namespace std;
bool CSearchBreadthFirst::FindPath(TerrainMap& terrain, unique_ptr<SNode> start, unique_ptr<SNode> goal, NodeList& path)
{
// Initialise Lists
NodeList closedList; // Closed list of nodes
NodeList openList; // Open list of nodes
unique_ptr<SNode>currentNode(new SNode); // Allows the current node to be stored
unique_ptr<SNode>nextNode(new SNode); // Allows the next nodes to be stored in the open list
// Boolean Variables
bool goalFound = false; // Returns true when the goal is found
// Start Search
openList.push_front(move(start)); // Push the start node onto the open list
// If there is data in the open list and the goal hasn't ben found
while (!openList.empty() || goalFound == false)
{
cout << endl << "Open list front:" << openList.front() << endl;
currentNode->x = openList.front()->x;
currentNode->y = openList.front()->y;
currentNode->score = openList.front()->score;
currentNode->parent = openList.front()->parent;
}
}
It's highlighting this line: currentNode->x = openList.front()->x; as the problem.
The NodeList type is defined in SearchBreadthfirst.h as the following:
using NodeList = deque<unique_ptr<SNode>>;
SNode is also defined in SearchBreadthfirst.h as such:
struct SNode
{
int x; // x coordinate
int y; // y coordinate
int score; // used in more complex algorithms
SNode* parent = 0; // note use of raw pointer here
};
The program breaks upon build. I've been trying to wrap my head around this for days now, so any help is greatly appreciated. If I've missed anything out, let me know and I'll add it in!
James

The error message Attempting to reference a deleted function is due to the fact that std::unique_ptr explicitly deletes its copy constructor because, obviously, there's only supposed to be one copy of the pointer it contains.
When you call
openList.push_front(start);
You're creating a copy of start which is of type unique_ptr<SNode> and it has a deleted copy constructor. In order to use a std::unique_ptr with a container, you need to move the object into the container. You need to do something like this:
openList.push_front(move(start));
That will move start into the deque and move what was in there into start.

Related

Tree traversal falls into infinite loop (with huffman algorithm implementation)

I am trying implementing the huffman algorithm following the steps described in this tutorial: https://www.programiz.com/dsa/huffman-coding, and so far I got this code:
void encode(string filename) {
List<HuffmanNode> priorityQueue;
List<Node<HuffmanNode>> encodeList;
BinaryTree<HuffmanNode> toEncode;
//Map<char, string> encodeTable;
fstream input;
input.open(filename, ios_base::in);
if (input.is_open()) {
char c;
while (!input.eof()) {
input.get(c);
HuffmanNode node;
node.data = c;
node.frequency = 1;
int pos = priorityQueue.find(node);
if(pos) {
HuffmanNode value = priorityQueue.get(pos)->getData();
value++;
priorityQueue.update(pos, value);
} else {
priorityQueue.insert(node);
}
}
}
input.close();
priorityQueue.sort();
for(int i=1; i<=priorityQueue.size(); i++)
encodeList.insert( priorityQueue.get(i) );
while(encodeList.size() > 1) {
Node<HuffmanNode> * left = new Node<HuffmanNode>(encodeList.get(1)->getData());
Node<HuffmanNode> * right = new Node<HuffmanNode>(encodeList.get(2)->getData());
HuffmanNode z;
z.data = 0;
z.frequency = left->getData().frequency + right->getData().frequency;
Node<HuffmanNode> z_node;
z_node.setData(z);
z_node.setPrevious(left);
z_node.setNext(right);
encodeList.remove(1);
encodeList.remove(1);
encodeList.insert(z_node);
}
Node<HuffmanNode> node_root = encodeList.get(1)->getData();
toEncode.setRoot(&node_root);
}
full code for the main.cpp here: https://pastebin.com/Uw5g9s7j.
When I try run this, the program read the bytes from the file, group each character by frequency and order the list, but when I try generate the huffman tree, I am unable to traverse this tree, always falling into a infinte loop (the method get stuck in the nodes containing the 2 first items from the priorityQueue above).
I tried the tree class with BinaryTree<int>, and everything works fine in this case, but with the code above the issue happens. The code for the tree is this (in the code, previous == left and next == right - I am using here the same Node class already implemented for my List class): https://pastebin.com/ZKLjuBc8.
The code for the List used in this example is: https://pastebin.com/Dprh1Pfa. And the code for the Node class used for both the List and the BinaryTree classes is: https://pastebin.com/ATLvYyft. Anyone can tell me what I am missing here? What I am getting wrong here?
UPDATE
I have tried a version using only c++ stl (with no custom List or BinaryTree implementations),but the same problem happened. The code is that: https://pastebin.com/q0wrVYBB.
Too many things to mention as comments so I'm using an answer, sorry:
So going top to bottom through the code:
Why are you defining all methods outside the class? That just makes the code so much harder to read and is much more work to type.
Node::Node()
NULL is C code, use nullptr. And why not use member initialization in the class?
class Node {
private:
T data{};
Node * previous{nullptr};
Node * next{nullptr};
...
Node::Node(Node * node) {
What is that supposed to be? You create a new node, copy the value and attach it to the existing list of Nodes like a Remora.
Is this supposed to replace the old Node? Be a move constructor?
Node::Node(T data)
Write
Node<T>::Node(T data_ = T{}) : data{data_} { }
and remove the default constructor. The member initialization from (1) initializes the remaining members.
Node::Node(T data, Node * previous, Node * next)
Again creating a Remora. This is not inserting into an existing list.
T Node::getData(), void Node::setData(T value)
If everyone can get and set data then just make it public. That will also mean it will work with cons Node<T>. Your functions are not const correct because you lack all the const versions.
Same for previous and next. But those should actually do something when you set the member. The node you point to should point back to you or made to do so:
void Node::setPrevious(Node * previous) {
// don't break an existing list
assert(this->previous == nullptr);
assert(previous->next == nullptr);
this->previous = previous;
previous->next = this;
}
Think about the copy and move constructors and assignment.
Follow the rule of 0/3/5: https://en.cppreference.com/w/cpp/language/rule_of_three . This goes for Node, List, ... all the classes.
List::List()
Simpler to use
Node<T> * first{nullptr};
List::~List()
You are deleting the elements of the list front to back, each time traversing the list from front till you find index number i. While horrible inefficient the front nodes have also already been deleted. This is "use after free".
void List::insert(T data)
this->first = new Node<T>();
this->first->setData(data);
just write
first = new Node<T>(data);
And if insert will append to the tail of the list then why not keep track of the tail so the insert runs in O(1)?
void List::update(int index, T data)
If you need access to a list by index that is a clear sign that you are using the wrong data structure. Use a vector, not a list, if you need this.
void List::remove(int index)
As mentioned in comments there are 2 memory leaks here. Also aux->next->previous still points at the deleted aux likely causing "use after free" later on.
int List::size()
Nothing wrong here, that's a first. But if you need this frequently you could keep track of the size of the list in the List class.
Node * List::get(int index)
Nothing wrong except the place where you use this has already freed the nodes so this blows up. Missing the const counterpart. And again a strong indication you should be using a vector.
void List::set(int index, Node * value)
What's this supposed to do? Replace the n-th node in a list with a new node? Insert the node at a specific position? What it actually does it follow the list for index steps and then assign the local variable aux the value of value. Meaning it does absolutely nothing, slowly.
int List::find(T data)
Why return an index? Why not return a reference to the node? Also const and non-const version.
void List::sort()
This code looks like a bubblesort. Assuming it wasn't totaly broken by all the previous issues, would be O(n^4). I'm assuming the if(jMin != i) is supposed to swap the two elements in the list. Well, it's not.
I'm giving up now. This is all just the support classes to implement the BinaryTree, which itself is just support. 565 lines of code before you even start with your actual problem and it seems a lot of it broken one way or another. None of it can work with the state Node and List are in. Especially with copy construction / copy assignment of lists.

How do I read multiple variables into a node?

So my project is to get a file called "contacts.txt", read in the data and put the data into a node. Then, I put that node into a list. I purge duplicates and print out the resulting list. I'm trying to get the reading in the data and the printing part down first but I'm having problem printing out my list.
A line of contact looks like:
Angelina M. Pierre 306 420 1235
And each part of the line (first name, middle initial, last name, phone number) is supposed to have their own variable. I'm not really sure what I'm doing wrong and I would appreciate the help. My code is:
#include <iostream>
#include <bits/stdc++.h>
#include <stdlib.h>
#include <fstream>
using namespace std;
class Node
{
public:
string firstName;
string middleI;
string lastName;
string phoneNum;
Node *next;
};
// This function prints contents of linked list
// starting from the given node
void printList(Node* n)
{
while (n != NULL) {
cout << n->firstName->middleI->lastName->phoneNum << endl;
n = n->next;
}
}
//This function reads the data from a file called "contacts"
//And streams each line into a new node.
void readData(Node* &p)
{
Node *newNode = new Node; /* Initializing the node*/
ifstream fin("C:\\Users\\owner\\Documents\\contacts.txt");
p = newNode;
while(!EOF){
//fin >> firstName >> middleI >> lastName >> phoneNum;
//while(getline(fin,newNode->contacts)){
newNode->firstName;
newNode->middleI;
newNode->lastName;
newNode->phoneNum;
newNode->next = new Node;
newNode = newNode->next;
}
}
// Driver code
int main()
{
Node *head;
readData(head);
printList(head);
return 0;
}
There are a couple things that I think are majorly detracting from your program's performance. In your printList function, you have the line cout << n->firstName->middleI->lastName->phoneNum << endl;, and I assume here you intend to print all of the information for a user. What is happening here, however, is that the program takes the pointer n, attempts to find the firstName property of the object being pointed to, then takes this property and attempts to find the middleI property of that property, then the lastName property of that property, etc. These fields of course do not exist, so your program will likely crash. Rather, I think using something like cout << n->firstName << " " << n->middleI << " " << n->lastName << " " << n->phoneNum << endl; would work better.
Also, in your readData function, your while loop will continue to update the singular node p instead of creating new nodes, so (assuming that your input file is properly formatted and all that jazz) your head node, which is what is passed into this function when it is called by main(), will only be equal to the last contact in your file and your list will have a length of 1.
Incidentally, I see that you only have a Node class. If you are wanting to work with lists, you probably should create a second class (i.e. LinkedList) that takes one more level of abstraction. Your Node class, then, will handle setting/reporting its data and answering which node follows it, and your LinkedList class will handle keeping track of the list (by remembering where the head is), adding to/deleting from the list, and finding specific nodes in the list.
Some other considerations:
Variables held by a class should almost always be private instead of public. The reason for encapsulating the information in the first place, aside from organizing it, is to make sure that other parts of the program that have no business altering this portion of your code cannot touch it, and you lose this safeguard when you make everything public.
The functions that you are using to create/add nodes, print lists, etc., should all be methods (i.e. functions of a particular class). Say I have some class, Foo, which has a function that acts upon it named bar. To implement it, I could write something like:
class Foo {
private:
//Foo's variables
public:
void bar() {
//bar's implementation
}
}
You will be able to use the method bar() elsewhere because it is labeled public, and bar() will be responsible for handling any necessary manipulation of Foo's information.
It is considered bad practice to use using namespace std; because it can sometimes lead to ambiguous function calls and adding std:: is more explicit. See here for more information.
Using the keyword NULL is very C-style, whereas nullptr is considered more proper (and even safer) in C++. If you are curious, this seems to give a pretty in-depth explanation of this change.
Using while(!fin.eof()) is also considered wrong because !fin.eof() will only return true after you have finished reading the input file. Thus, you will attempt to read past the end of the file and this is plain dangerous. See here for more information.
A little lengthy, but I hope this clarifies things for you a bit! Feel free to comment if you have any questions.

C++: Issue Creating New Instance of Class After Current Instance Destroyed

I am working on a Binary Search Tree (BST) program. Per the assignment's requirements, the user loads a text file to construct the tree. If the user would like, they can then create a new tree by loading a new text file. Loading a new text file should destroy the old tree.
To accommodate this require, my method to create a new tree, readNewFile(), first checks if a tree already exists. If it does, it runs the destructor on the tree. However, I then need to create a new tree, that exists outside the scope of readNewFile(), so that it can be accessed globally. Is this possible to do? If so, could you please explain how?
My reduced code:
int main() {
//BST
BST rootTree;
readNewFile(rootTree);
readNewFile(rootTree);
return 0;
}
void readNewFile(BST& tree) {
ifstream inFile;
string fileName;
// if tree was previously filled, destroy it
if (tree.rootPtr() != NULL) {
tree.~BST();
BST tree = new BST();
}
cout << "\nEnter file to load: ";
cin.ignore();
getline(cin, fileName);
cout << "Opening file " << fileName << endl;
inFile.open(fileName.c_str(), ios::in);
// Populates tree... //
}
Destructor (within BST.hpp):
BST::~BST() {
destroyTree(root);
}
void BST::destroyTree(TreeNode*& treePtr) {
if (treePtr != NULL) {
destroyTree(treePtr->leftChildPtr);
destroyTree(treePtr->rightChildPtr);
delete treePtr;
}
}
This returns a segfault, which makes sense, since the tree was destroyed. However, is there a way I can create a new tree, with the same scope as the destroyed BST rootTree?
One way to accomplish the requirement is to have a method called del() in your BST class. All it does is delete all the nodes of the tree but not the root pointer. This is the pointer that points to the root node. After calling del(), you can start creating a new tree. The pseudo code would look something like this:
// if tree was previously filled, destroy it
if (tree.rootPtr() != NULL) {
tree.del()
}
// read the input file
// Start inserting the new nodes
First off: what's wrong with the code.
As you already pointed out, if the tree is destroyed, you can't be using it again. In this case, it's double-bad: by calling the destructor on BST in readNewFile(), you're causing the destructor to be called twice -- once when you explicitly call it, and the second time when the local instance in main() goes out of scope. This is bad.
Now about how to fix it:
The easiest way would just to declare rootTree as a pointer inside main(), and then make readNewFile() take a pointer-to-pointer as an argument. readNewFile() would destroy the existing tree pointed to by the pointer, and then reset the pointer to point at the new tree it creates. Simple.
What would be a better design, though, would be to make readNewFile() a member function of BST. Then main() should construct a new BST and call that instance's readNewFile().
You never invoke the destructor directly unless you know pretty well what you're doing. And then, it's typically because it was created using placement new. Further, "T t = new T;" doesn't make sense, assigning a pointer-to-T to a T. My guess is you are reproducing a Javaism here, but the object models of these two languages are too different.

Find an edge using the Ford Fulkerson algorithm?

I'm trying to implement the Ford Fulkerson Algorithm in C++.
However, I'm having trouble with my find_edge function. When I call this function in my_alg, it chooses the correct edge and then the flow is incremented in my_alg. It chooses the right edge and increment its flow (flow), but when I call the find_edge function again, the flow is not incremented as it should be.
This results in an endless loop of my algorithm. Probably I do something wrong with the pointers. You can see my code below.
//An object of this class represents an edge in the graph.
class Edge
{
private:
//Node *prev;
public:
int flow;
Edge(Node *firstNode, Node *secNode, unsigned inCost) {
orgNode = firstNode;
dstNode = secNode;
bridge_capacity = inCost;
}
Edge() {
flow=0;
}
};
//An object of this class holds a vertex of the graph
class Node
{
public:
Node *prev;
vector<Edge>& getAdjNodeList() {
return adjNodeList;
}
};
Edge *find_edge(Graph *g,Node *from,Node *to) {
vector<Edge> b=from->getAdjNodeList();
for(int i=0;i<b.size();i++) {
if(b[i].getDstNode()==to)
return (&b[i]);
}
return NULL;
}
int my_alg(Graph *as,Node *source,Node *sink){
Edge *find_edge();
int max_flow=0;
while(bfs(as,source,sink)) {
Node *b=as->nodeList[num_isl];
int inc=100000000;
while(b->prev!=NULL) {
Edge *bok=find_edge(as,b->prev,b);
inc=min(inc,bok->get_bridge_capacity()-bok->flow);
b=b->prev;
}
b=as->nodeList[num_isl];
while(b->prev!=NULL){
Edge *bok = find_edge(as,b->prev,b);
bok->flow += inc; // This is the place the flow is incremented
bout << bok->flow; // Here, everything is alright.
bok = find_edge(as,b->prev,b);
cout << bok->flow; // However, this is is not the correct result.
}
max_flow+=inc;
}
return max_flow;
}
I had a more thorough look at your code. To help you track your problems down yourself in the future, I will show you a sample process of finding the error.
If you really can not find the problem by looking at the code, you may want to strip down everything that obfuscates your view on the problem. The reduced code could look like this:
class Edge {
public:
int flow;
};
class Node {
private:
vector<Edge> adjNodeList; // list of outgoing edges for this vertex
public:
vector<Edge> & getAdjNodeList() {
return adjNodeList;
}
void addAdjNode(Node* newAdj) {
adjNodeList.push_back(Edge(newAdj));
}
};
int main() {
Node *node1 = new Node();
Node *node2 = new Node();
node1->addAdjNode(node2);
vector<Edge> t = node1->getAdjNodeList();
vector<Edge> f = node1->getAdjNodeList();
t[0].flow = 11;
cout << t[0] << endl;
cout << f[0] << endl;
}
If you would run this code, you would notice that t[0] and f[0] are not the same. As I just copied the crucial elements of your code, the reason should still be the same.
What is happening here? When calling
vector<Edge> t = node1->getAdjNodeList();
the adjacency list is returned by reference, which should leave you with a reference to the original list - you should be able to change it's elements, shouldn't you? However, when assigning this reference to the newly allocated vector t, the implicit copy constructor is called, thus t will contain a copy (!) of your vector while you wanted to save a reference.
To get around this problem, you could just have done the following:
vector<Edge> & t = node1->getAdjNodeList();
which saves the reference and does not create a new object.
I can only assume why the pointers happened to be identical between calls to the function: The object probably was copied to the same place every time. Furthermore, note that you increased the value of an object that did not exist anymore - the copy was deleted with the end of the find_edge-call.
It took some time to give an answer to your question as you did not track the problem down yourself. If you had given the example above, I bet your solution would have been there within a matter of minutes. You are encouraged to raise your problems here at stack overflow - however, most members will not be willing to work through a lot of code to identify the problem themselves. That means, high quality answers usually require questions that directly come to the point. (The last paragraph was intended to help you in the future, however, it could be reduced without altering the question).
Apart from that, I would strongly encourage you not to use your objects the way you do. By passing everything as references and making all changes outside the object, you essentially bypass the encapsulation that makes object orientated programming that powerful. For example, it would be much wiser (and would not have given you your problem) if you just had added another function increaseFlow(Edge* to, int increment) to your Node and had done everything within the object.
Hope I could help.

STL List copies a struct, but the copied values are offset by two memory addresses

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.