I haven't been working with C++ for a long time and now I need to do some small "project".
I reviewed few topics trying to find solution for my problem with no results...
Here is "pseudo-code" (Pair is my class):
Pair** pairs;
I get size of table from input and create table of pointers:
pairs = new Pair*[size];
I have a loop which creates some object and puts it's reference into table of pointers. More or less:
while (...)
{
Pair pair(...); // calling constructor, creating object type of Pair.
pairs[i] = &pair;
i++;
}
The problem is that &pair is the same number everytime (every step of loop).
Let's say the address of first created object is 1234.
So with every step in loop it overrides this object at 1234. So each pointer in pairs points to the same address -> same object.
I would like to force creating this object at new place in memory.
I've been trying to put those objects into other table and then pass their reference to table of pointers:
Pair* clearPairs = new Pair[size];
while (...)
{
clearPairs[i] = Pair(...);
pairs[i] = &clearPairs[i];
i++;
}
But problem still occurs.
Any tips?, mistakes/errors in my code (or thinking)? Shall I implement some "copying constructor"?
while (...)
{
Pair pair(...); // calling constructor, creating object type of Pair.
pairs[i] = &pair;
i++;
}
pair is allocated with automatic storage duration and goes out of scope upon each iteration of the loop. You are saving a pointer to an invalid object (a bunch of them).
You should use a collection of smart pointers if you really need pointers (this is true when objects cannot be copied or copies are expensive), which may not be necessary at all. Try this instead:
vector<Pair> pairs;
// and if you need pointers...
vector<unique_ptr<Pair>> pairs;
while(whatever) {
pairs.push_back(Pair(...));
// or...
pairs.push_back(unique_ptr<Pair>(new Pair(...)));
}
Related
Though I've a lot of experience as C Embedded Programmer, I'm actually not so skilled in C++. I'm implementing a parser in which ItemsToBeFound are pushed within a list.
It happens that some of these items (let's say master items) carry more information, so that some other items (slave items) need to refer to master items to retrieve those info. This link is done at population phase, without iterators.
This is the sequence of the actions:
I save the pointer to the master item, and push it to the list
I set specific pointer field pReferenceItem of the slave item so that it points to the master item
Later, I start the iteration through the list
I save parsed information to master item
When it comes to process slave item, I try accessing master item's field. But it is unchanged!
The pointer to master item during iteration is different from the original one, so the pointer contained in slave item points to the original (unchanged) data
Any suggestion about some special qualifiers I could use in order to force the iteration through the original data? Any obvious mistake in the way I issue lists and/or iterators?
Please note that I'm sure about what asserted in step #6 above, because I've watched pointers values using the debugger.
Here's the simplified code showing the described issue:
#include <list>
#include <iostream>
std::list<ItemToBeFound> myList;
class ItemToBeFound
{
private:
public:
/* ... */
int specialDataToBeRetreived;
ItemToBeFound *pReferenceItem;
/* ... */
ItemToBeFound( ItemToBeFound *ref )
{
pReferenceItem = ref;
specialDataToBeRetreived = 777;
}
bool isMaster( void )
{
return ( pReferenceItem == NULL );
}
}
void PopulateList( void )
{
ItemToBeFound *masterItem = new ItemToBeFound( NULL /* no refItem */ );
myList.push_back( *masterItem );
ItemToBeFound *slaveItem = new ItemToBeFound( masterItem );
myList.push_back( *slaveItem );
}
int main( void )
{
// ...
PopulateList();
// ...
/* Let's iterate and do something */
std::list<ItemToBeFound>::iterator it = myList.begin();
while( it != itemsList.end() )
{
if( it->isMaster() )
{
it->specialDataToBeRetreived = 42; /* In the real program I get the value after a parsing activity */
}
else /* it is a slave item */
{
it->specialDataToBeRetreived = it->referenceItem->specialDataToBeRetreived;
/* But it doesn't work! */
std::cout << "Updated special value: " << it->specialDataToBeRetreived << std::endl;
}
it++;
}
// ...
return 0;
}
In the "slave" branch of the conditional, during iteration, I expect the specialDataToBeRetreived I set in reference object, but I keep obtaining 777 (the example value I set in the constructor):
Updated special value: 777
And the reason why I get this value is that, as shown by the debugger, the reference item in iteration phase has an address different from the original one, pointed by the slave item.
The questions
Why did this change occur?
I was expecting that the pointer to my object was just copied to the list, like in many list implementation I've seen in my life. Does the push_back method of the std::list template perform a copy of the pointed object?
Iterators do not copy anything. In C terms, they behave almost like pointers within array.
However, you do copy elements here:
void PopulateList( void )
{
ItemToBeFound *masterItem = new ItemToBeFound( NULL /* no refItem */ );
myList.push_back( *masterItem ); //copy of masterItem pointee
ItemToBeFound *slaveItem = new ItemToBeFound( masterItem ); //initialized with masterItem, which does not point to the object stored in the list!
myList.push_back( *slaveItem ); //copy of slaveItem pointee, also stores masterItem, but not object from the list
//slaveItem is leaked here, masterItem is only kept via slaveItem copy in the list
}
If you initialize objects like this, your slave objects never store pointers to objects in the list, but rather to the objects created with new.
Let's go step by step through the code (I'll be a rubber debugger here):
ItemToBeFound *masterItem = new ItemToBeFound( NULL /* no refItem */ );
You allocate an object on the heap (they don't have names, but let's call it m1) and a pointer on the stack called masterItem, so derefenced masterItem is exactly m1.
myList.push_back( *masterItem );
std::list::push_back() creates a copy of the argument given to it (I ignore move semantics - they are not used here). Notice what is the argument - dereferenced masterItem or m1 as we called it before.
The copy of the object m1 created by push_back will be called m2
So now we have the following (with a->b meaning a points to b):
masterItem->m1
myList->m2
Next line:
ItemToBeFound *slaveItem = new ItemToBeFound( masterItem );
Here, you initialize slaveItem with new object on the heap - s1.
masterItem->m1
myList->m2
slaveItem->s1->masterItem->m1 (s1 points to masterItem, which points to m1)
Last one:
myList.push_back( *slaveItem );
Again, push_back() creates a copy of its argument on the heap (this copy will be called s2)
masterItem->m1
slaveItem->s1->masterItem->m1
myList->m2
myList->s2->masterItem->m1
Eventually, you have:
4 objects on the heap: m1, m2, s1 and s2 (all of type ItemToBeFound)
2 objects on the stack: masterItem and slaveItem (both of pointer type)
one object in the global area: myList (can be treated as stack object here)
m2 and s2 are stored in myList and can be iterated over
Both s1 and s2 have pointers to m1
No slave object points to m2
Later on, when you run mainFunction(), object m2 gets filled with data, but object s2 is trying to retrieve data from m1, which wasn't filled with any valueable data.
It's hard to propose any solution without more info. One I'd use if I couldn't reorganize class structure would be to use std::list<std::shared_ptr<ItemToBeFound>> instead, which will keep your pointers safe, and only store std::weak_ptr<ItemToBeFound> referenceItem in slave objects (to avoid any circular dependecies and declare ownership clearly).
You could have std::list<ItemToBeFound*> and manage memory manually, but that's against modern C++ spirit and should be used with great care - flow can take more branches in C++ than in C and it's more difficult to track all of them to delete everything.
You could technically store in slave objects pointers to objects stored in the list (or even iterators to those), but that feels like a weird solution. You don't control those objects and you don't own them, so you shouldn't keep pointers to those.
My task is to construct a compiler which lexes, parses and analyses the resultant Abstract Syntax Tree to ensure type matching, avoid duplicate declaration etc.
It was instructed for us to construct a Symbol Table, which holds a map of variables and their types for each scope. I opted for a vector of maps. I preferred this over a stack since I can iterate over it when checking for variables at any scope.
I constructed Push, Pop, Lookup and Insert operations for this structure as shown below and my idea was to hold a reference to the latest map in the vector and add variables to it. As a new scope is entered a push operation is carried out creating a new map in the vector within which to store the arrays.
When a scope is exited a Pop operation is done to remove the map at the end of the vector and acquire the previous map which is now at the back of the vector.
Via debugging I've noticed the vector is simply holding no map details and working by reference seems to be doing nothing to update the vector that's supposed to be holding this map. How do I correctly reference a map inside a vector and maintain this structure?
Symbol Table:
struct SymbolTable {
// Stack defining scopes holding identifier / type details
std::vector<std::map<std::string,std::string>> _scopeVector;
// Tracks current working stack
std::map<std::string,std::string> _currentMap;
SymbolTable() = default;
void Push() {
std::map<std::string,std::string> *_tempMap;
_tempMap = new std::map<std::string,std::string>();
_scopeVector.push_back(*_tempMap);
_currentMap = _scopeVector.back();
}
void Insert(std::string p_name, std::string p_type) {
_currentMap.insert(std::make_pair(p_name,p_type));
}
// Returns type if found, empty if not
std::string Lookup (std::string p_name) {
for (int i = 0; i < _scopeVector.size(); i++) {
if (_scopeVector[i].find(p_name) == _scopeVector[i].end()) {
// No match yet
} else {
return _scopeVector[i].find(p_name)->first; // return var name
}
}
std::cerr << "Type name " << p_name << " not found in all of stack" << std::endl;
return "";
}
void Pop () {
_scopeVector.pop_back();
_currentMap = _scopeVector.back();
}
};
SymbolTable *ST;
Class constructor which sets up the Symbol Table:
SemanticAnalysisVisitor() {
ST = new SymbolTable();
ST->Push();
}
Debugger image of an empty vector but populated map
As for your problem (I think) the statement
_currentMap = _scopeVector.back();
copies the map from the vector.
_currentMap will always be a separate and distinct map, totally unrelated from whatever is in the vector.
It seems you want to use references, but that's not possible in this case (unless you do a redesign).
You could solve this problem (and the memory leak I mentioned in a comment) by having a vector of (smart) pointers to the maps, and make _currentMap a (smart) pointer as well.
So I've completely edited my question.
I have a map called mTextMap which contains:
typedef std::map<const std::string, Text*> TextMap;
TextMap mTextMap;
And I have the following methods:
void Foo::setUpGame()
{
Text text(1,2,3,4); //create a Text object
mTextMap["MainText"] = &text; //save it in the map!
}
Text& Foo::getText(const std::string name)
{
auto i= mTextMap.find(name);
return *(i->second); //Gets a reference to the Text that is inside the map
}
Now if I use this way:
Foo foo;
foo.setUpGame();
Text& myText = foo.getText("MainText"); // Why is this corrupted?
The object myText is completely corrupted!!
Why is this happening?
The general problem seems to be, that you think that this line:
mTextMap["MainText"] = &text;
stores the text object in the map. IT DOESN'T! It stores a pointer to the object in the map and the text object itself will - as you said yourself - automatically be destructed at the end of the function. So now your pointer points to a non-existing object, which leads to the observed errors.
There are various solutions to your problem, depending on what exactly, you try to achieve and what you are going to do with your class.
One possibility is to use a map of Text objects (instead of pointers):
typedef std::map<const std::string, Text> TextMap;
void Foo::setUpGame()
{
Text text(1, 2, 3, 4); //create a Text object
mTextMap["MainText"] = text; //copy it into the map!
}
or
void Foo::setUpGame()
{
mTextMap.emplace("MainText", Text(1, 2, 3, 4)); //Doesn't require Text to be default constructable
}
Another possibility is to create the text objects on the heap and use smart pointers (e.g. unique_ptr)
typedef std::map<const std::string, std::unique_ptr<Text>> TextMap;
void Foo::setUpGame()
{
mTextMap["MainText"] = std::make_unique<Text>(1,2,3,4); //create object on the heap an store a pointer to it in the map
}
The std::unique_ptr will automatically destroy the text object, as soon as the map gets destroyed.
If you really need to have a map of raw pointers for some reason, you can use "new" as explained by David, but don't forget to delete them when you don't use them anymore - c++ doesn't have a garbage collector (like e.g. java) that would take care of this automatically.
The "text" object is going out of scope as soon as setUpGame completes. At this point, the heap memory is freed up to be overwritten by any new use of the heap. It is essentially a temporary scratchpad of items that only exists within the scope of a function (or within explicit scope operators inside a function).
David G's advice is sound: read more about the difference between stack and heap memory, and also consider the advice to use smart pointers. However, if you want a cheap, dirty fix to your immediate problem, you can try this:
void Foo::setUpGame()
{
static Text text(1,2,3,4); // Note use of "static" keyword
mTextMap["MainText"] = &text; //save it in the map!
}
Whilst I do not advocate the use of static as a shortcut to solving more fundamental architectural memory issues, you can use this as a short-term measure if you're desperate to get things working. Labeling the object as static ensures its lifetime will outlive the scope of the function. But I would not recommend it as a long-term solution to this kind of issue.
When you dynamically allocate memory for your object, it will live as long as you do not explicitly delete it from memory, it is not deleted after you exit the method it was created in, so you can put a pointer to it in a map and it will always be there (just be sure you delete the memory when removing the object from the map).
You can test this with the following simple code, where I declare a new Int in a function, return a pointer to the memory and print it in the other function that received the map (with the pointer in it). It prints correctly, which means the memory was not freed even when out of scope.
#include <iostream>
#include <map>
std::map<std::string, int*> myMap(){
int* test = new int(1);
std::map<std::string, int*> ObjMap;
ObjMap["object"] = test;
return ObjMap;
}
int main(int argc, const char * argv[]) {
// insert code here...
std::map<std::string, int*> mmap = myMap();
std::cout << *mmap["object"] << std::endl;
return 0;
}
So to answer your question, create your object dynamically like this:
Obj* obj = new obj(1,2,3,4);
And it will not be deleted when out of scope. Still, you need to delete the memory yourself unless you use Smart Pointer, like this: delete obj; (when you remove it from the map, to free the memory as it will not be freed automatically).
PS: You should read on how the Stack and Heap works and how Dynamic and Static allocation works (using the stack OR the heap). See this c++ dynamic memory allocation tutorial to have more informations.
Like MikeMB said, using Smart Pointers is easier as you will be sure you deleted the memory, and you will also be sure you never access a deleted memory. See this Stack Overflow topic for smart pointers informations: What is a smart pointer and when should I use one?
I am storing multiple objects in a vector of pointers to these objects, like so, in C++:
vector<Host *> somevector;
I then initialize each item like this:
somevector.push_back(new Host(x));
The object takes an initializing argument.
As I read through data (strings) and end up with a list of object pointers, I add them to an internal vector inside the object itself:
somevector.at(i)->add(string data);
However, it appears that all the data have been added to the same object, and even though the objects have different names, their internal vector that stores this data are identical.
I searched various keywords to solve this and I think it is an issue with a copy constructor (I currently am using default). How do I account for the vector inside the object that I am copying? Do I have to make the vector in the object a field so that a new one is created in the copy constructor?
EDIT:
I've replicated the code for the object class:
vector<string> v;
Host::Host(string _x): x(_x)
{
}
Host::~Host()
{
}
string Host::name()
{
return x;
}
string Host::link(int r)
{
int i = r % v.size();
return v.at(i);
}
void Host::add(string data)
{
v.push_back(data);
}
So I am using this vector inside the host object to store a bunch of strings. Then, when I call link from my main program, I pass it a random number, and I want to get a random string from the list inside the object. However, my link() calls are coming back with strings that should not have been stored into the object.
From what I can see from the example code you have posted 'v' isn't a member object of Host. So calls to Host::add are simply pushing back to a globally available vector. Is this perhaps where your problem is?
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.