I am creating a grid game in which each box in the grid is a district and represents some people along with their specific ID.
Now I have a function here which locates where the exact person is in the grid in particular box.
Here is my function.
bool where(int id, int &row, int &col)const
{
person* per;
for(int i=0;i<alive.size();i++)
{
std::cout<<alive[i]<<std::endl; //This is just for testing the person number
if (alive[i]->person_id == id)
{
p = alive[i];
break;
}
}
}
My Question: The test code std::cout<<alive[i]<<std::endl; is always printing the address of the number. I tried many things but I couldn't figure it out.
Edit: Here alive is a vector
Can anyone please help me.
Consider this line in your code: if (alive[i]->person_id == id). The fact that it uses -> rather than . indicates that alive isn't a vector of some struct/class, but is rather a vector of pointers (or potentially some other object that acts like a pointer) to some struct/class. As such, to print the actual object, do std::cout<<*alive[i]<<std::endl; (note the added *).
Related
I am new to CPP and I am writing a program as an assignment to simulate a train path system that includes destinations and starts using object oriented programming .
I have 2 classes as shown below (there is a a passenger class but it is not relevant ) :
class Train
{
public:
int cooldown_time;
int travel_time;
int time_since_movement;
int id;
class Station *start;
class Station *destination;
vector<Passenger *> current_passengers;
string status;
void add_train(vector<string> commands, vector<Station> stations, vector<Train> &trains)
{
travel_time = stoi(commands[THIRD_PART + 1]);
cooldown_time = stoi(commands[THIRD_PART + 2]);
status = TSTATUS1;
start = station_search(stations, commands[SECOND_PART]); // this is where the problem happens
destination = station_search(stations, commands[THIRD_PART]);
id = stations.size();
}
};
class Station
{
public:
int tuffy_price;
string city_name;
vector<Passenger *> current_passengers;
vector<Train *> current_trains;
int id;
void add_station(vector<Station> &stations, vector<string> &commands)
{
tuffy_price = stoi(commands[THIRD_PART]);
city_name = commands[SECOND_PART];
id = stations.size();
}
};
I have a search function dedicated to finding the start and destination based off a command that user enters for example :the user enters "add_train cityname1 cityname2 <cooldown_time> <travel_time>". my program detects the city names and searches a vector I have named stations with a key that is the city name and returns a pointer (because of the complications in memory behavior in a function , i set it to pointer) to that station-object .
the function is as below :
Station *station_search(vector<Station> stations, string key)
{
Station *dummy;
for (int i = 0; i < stations.size(); i++)
{
if (stations[i].city_name == key)
{
return &stations[i];
}
}
return dummy;
}}
my problem is with my search function's weird behavior , when I debug the program I see the function find the correct station object and return a pointer to it ,but when the execution returns to the constructor function it randomly (maybe not randomly ) turns the first pointer relating to the start station to null and replaces the values inside with garbage ones.
but after the function searches for the destination station it does not do this and the execution is correct.
Could someone explain why this error is occurring?
My guess is that I have not understood local variables and pointer returns well enough and I have committed a rookie mistake somewhere but I don't seem to find it .
PS: I did not include the full code as it's too long I can include it by attaching a file ,comment down if it's necessary.
Station *station_search(vector<Station> stations, string key)
If you take a closer look here, you will see that the stations parameter is passed by value, which means that after this function returns, this stations parameters will get destroyed. It will be no more. It will cease to exist. It will become an ex-parameter.
However this station_search returns a pointer to some value in this vector. Therefore, rules of logic dictate that it will return a pointer to a destroyed object. Attempting to dereference that pointer, in any way, becomes undefined behavior.
Your other class methods receive parameters by reference, so you must already understand the difference between passing parameters by value vs. by reference, so you should simply do the same here.
Here you are passing a copy of the vector, which is destroyed when the function returns. Additionally, if the key is not found an uninitialized pointer is returned.
Station *station_search(vector<Station> stations, string key)
{
for (Station &station : stations)
{
if (stations.city_name == key)
{
// Pointer becomes invalid when you leave.
// Accessing this pointer will cause undefined behavior.
return &station;
}
}
// This would always cause undefined behavior as dummy was not initialized.
return nullptr;
}
You should pass in a reference and initialize dummy:
Station *station_search(vector<Station> &stations, string key)
I'm trying to create a framework for a Room in a text game exercise. The way the game works is that Rooms are classes, which contain pointers to arrays of pointers to Tiles, and each tile has a pointer to a Container that represents items that are on the Tile.
The implementation of this is pretty simple, and it compiles fine. I'm having some problems, however, when I try to 'place' a Thing object 'onto' a Tile. This is done through passing a pointer to a Thing object through multiple passthrough functions. The pointer is passed to the Tile's placeOnTile(Thing * i) function, which passes it to the Tile's Container's addItem(Thing* th) function, which runs a simple check to make sure it fits in the Container (with a compare to a maxSize int), then returns true if it does fit.
According to a debug watch, the pointer (named placer) is not changing through the passes (this is good). However, when it reaches the final passthrough function (that of the Container's addItem(Thing* th)), it will segfault and not continue running the program.
The relevant code samples I could think of are listed below. If there is more I should include please let me know.
in main:
cout << "Bedroom Demo" << endl << endl;
cout << "Creating bedroom obj...";
Bedroom b1; //this calls the constructor for Bedroom
cout << "done." << endl << endl;
in Bedroom.h:
Bedroom() //constructor
{
makeNineSquare(1); //this creates an arry of 9 Tiles, arranged in a 3x3 grid
Thing* placer; //this will point to objects that you'll create
placer = new Bed("Your bed","This is your bed.",false,false,true,1); //constructor
ti[2]->placeOnTile(placer); //!!!!This is where the error occurs!!!!
placer = new Decor("North-facing Window","The window to the north looks out into barren space",false,false,true);
ti[1]->placeOnTile(placer);
placer = new Desk("Your desk","Your desk is wooden and antique.",0,0,1,5);
ti[3]->placeOnTile(placer);
delete placer; //for memory leaks
}
in Tile.h:
bool placeOnTile(Thing * i){return onTile->addItem(i);}
in Container.h (onTile is a Container object encapsulated in Tile):
bool addItem(Thing* th);
in Container.cpp:
bool Container::addItem(Thing* th)
{
if (numItems < maxSize)
{
contents[++numItems] = th;
return true;
}
else return false;
}
As I mentioned above, a debug watch shows that every step of the 'passing' works fine except the final passthrough (that of Container). What am I doing wrong?
Note: ti is declared inside Bedroom. It's an array of 9 tiles, 0 through 8, that make up the 'room'. The function makeNineSquare is just a function that implements a two-dimensional linked list on the array, creating NESW pointers to the adjacent Tiles. The reason I've created it like this is to facilitate placement on certain tiles with the array (as shown in the code provided), and to facilitate easy traversal of the grid by an object (such as a Player) with the pointers.
This also allows for global, generic move commands (moveN is just curr = curr->getN instead of a calculation to determine if, say, 7 is adjacent to 2).
According to your code I have no idea what numitems is but check if numitems++ is causing an array out of index.
So say I have
Class Person{
private:
Person* _friends[10];
public:
//All methods listed below. Except for the main one, that is.
}
Person::Person()
{
for(int i=0; i < 10; i++)
_friends[10] = 0;
}
Person* Person::getFriends()
{
return _friends;
}
void Person::addFriend(Person* buddy) //Assume it's fully functional.
{
//code for adding a friend.
}
void Person::operator=(Person& p)
{
for(int i = 0; i < 10; i++)
_friends[i] = p.getFriends()[i];
}
int main()
{
int user1size = 10;
int user2size = 30;
Person* user1 = new Person[10];
Person* user2 = new Person[10];
//assume these 4 next lines will be repeated with different values a few more times, in more intricate ways, by the magic of for/while loops.
user1[0] = new Person();
user2[9] = new Person();
user1[0].addFriend(user[9]);
user1[9].addFriend(user[0]);
for(int i = 0; i < user1size; i++)
{
user2[i] = user1[i]; //Here is where the paradox starts.
}
delete [] user1;
return 0;
}
So well, my question is where does it stop? I mean, my intent is to only copy the reference to the Person objects inside the _friends array, but I understand that might be little to no possible, so the solution is to keep "copying" these Person objects too, who in turn also have a list of friends, and these friends also have friends and so on. I know it has to stop somewhere, but I don't really want it to go all the way through and not to even mention I don't want some Person objects to be over-copied or catch in an infinite loop.
so how to solve this paradox?
P.S. : Please understand if my code has a lot of mistakes or is crappy. I made it in the go and all I intend with it is to make you all catch the general idea.
P.S.2: I cannot use any other library other than <ostream>, yup sucks for me.
P.S.3: Any website/article you could provide me to read about this would make me so happy! Thank you beforehand.
Well, first of all, what you probably want to do is to just copy the pointers as they are.
Why? Because if person "A" has a friend "F", and person "B" has the friend "F" as well, they will probably refer to the same person "F" object. If you make a deep-copy as you suggested, and you copy A to A2 and B to B2, you will have a total of three distinct person "F" objects -- the original, referenced from A and B, a copy referenced from A2, and another copy referenced from B2.
Of course, this might be what you want; I can't know that. But in many cases it's not.
The whole pointer setup will work just fine, although you have to be careful with memory management: you can easily end up with pointers to persons that no longer exist
If you do want to do a deep copy (a "deep copy" is a copy where referenced objects are copied too) you'll have to find cycles yourself, for example by tracking which objects you have copied already. I won't be trying to sketch something like this now, as it can get somewhat complicated and I don't think you actually want to deep copy your "person" objects.
There is no paradox because you are not doing a deep copy. Check out this declaration:
Person* _friends[10];
This says _friends is an array of pointers to Person objects. Correctly copying in operator=() this array will not call operator=() on each Person in the array.
However, the following function will not compile:
Person* Person::getFriends()
{
return _friends;
}
The return type and the type of _friends does not match. This is why it is important to post code that compiles and exactly reproduces the problem you have encountered.
IIUC, you want to know how to handle copies of graphs of objects, and you want to maintain their connections in the graph. Let's say Joe has a friend Bill and Bill has a friend Joe, and you copy Joe (lets name the copy Joe'), you want Joe' also have a friend who has (reflexively) Joe' as a friend. This problem typically comes up when programming compilers.
The easiest way to actually do this is never do any copies. Let the objects reside in their memory locations, use references/pointers to them all the time and modify them destructively.
However, it is sometimes needed to copy the objects, possibly modifying the graph (in the compiler scenario, that might mean eg. inlining a function). In that case, you employ a simple graph traversing algorithm, the DFS, roughly like this:
// o will be the object to copy
// m will be a map (old object -> new object)
copy(object* o, map& m) {
if(m.contains(o))
return m[o];
object* n = allocate new object;
m[o] = n; // set the map beforehand, in case we have some back edges from this subtree
n.subobject = copy(o.subobject, m); // for each subobject, or relation. In your case, friend
return n;
}
If you want just to move some object to a new location, you can just traverse the whole graph and overwrite the pointers. This is much easier if you have back edges in your graph, too (ie. not only "friends", but also "people whose friend I am"). Still, the best option is to avoid it; that means not creating arrays of Persons that might grow and make arrays of Person*s, so that the real Person still stay in the same memory location.
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.
I'm having an issue where using vector.push_back(value) is overwriting the final value, rather than appending to the end. Why might this happen? I have a sample item in the vector, so it's size never hits zero. Below is the code..
void UpdateTable(vector<MyStruct> *Individuals, MyStruct entry)
{
MyStruct someEntry;
bool isNewEntry = true;
for (int i = 0; i < Individuals->size(); i++)
{
if (!(strcmp(Individuals->at(i).sourceAddress, entry.sourceAddress)))
{
isNewEntry = false;
//snip. some work done here.
}
}
if(isNewEntry)
{
Individuals->push_back(entry);
}
}
This let's my first "sample" value stay in, and will allow for just one more item in the vector. When 2 new entries are added, the second overwrites the first, so the size is never larger than 2.
edit: More code, since this is apparently not the issue?
void *TableManagement(void *arg)
{
//NDP table to store discovered devices.
//Filled with a row of sample data.
vector<MyStruct> discoveryTable;
MyStruct sample;
sample.sourceAddress = "Sample";
sample.lastSeen = -1;
sample.beaconReceived = 1;
discoveryTable.push_back(sample);
srand(time(NULL));
while(1)
{
int sleepTime = rand() % 3;
sleep(sleepTime);
MyStruct newDiscovery = ReceivedValue();
if (newDiscovery.lastSeen != -1000) //no new value from receivedValue()
{
UpdateTable(&discoveryTable, newDiscovery);
}
printTable(&discoveryTable);
}
return NULL;
}
I'm going to hazard a guess:
Suppose MyStruct is declared like
struct MyStruct
{
const char *sourceAddress;
// Other Gubbins ...
};
And that ReceivedValue does something like
MyStruct ReceivedValue()
{
static char nameBuffer[MAX_NAME_LEN];
// Do some work to get the value, put the name in the buffer
MyStruct s;
s.sourceAddress = nameBuffer;
// Fill out the rest of MyStruct
return s;
}
Now, every structure you push into your vector has sourceAddress pointing to the same global buffer, every time you call ReceivedValue it overwrites that buffer with the new string - so every entry in your vector ends up with the same string.
I can't be sure without seeing the rest of your code, but I can be sure that if you follow some of the good C++ style suggestions in the comments to your question this possiblity would go away.
Edit for clarification: there's no need to heap allocate your structures, simply declaring sourceAddress as a std::string would be sufficient to eliminate this possibility.
The scope for the items you are pushing into the database is expiring. They're being destructed when you leave the {} in which they were created - and as such the reference to them is no longer valid.
You need to change it from vector<MyStruct> to vector<MyStruct*> (preferably using safe pointers from Boost:: instead of pointers, but you get the idea).
You are creating the item within the (limited) scope and pushing it onto the vector (while the struct is copied, the strings in it are not!) it then reuses the same memory location (most likely if properly optimized) to store the next "new" struct and the one after that and so on and so forth.
Instead, within the limited scope create MyStruct *myObject = new MyStruct and assign its values, then push the pointer to the vector.
Remember to delete all values from the vector before clearing it/destroying it!!
Or, of course, you could use std::string/CString/whatever instead of a char array and avoid the issue entirely by having a safe-to-copy struct.
ComputerGuru's answer works however there in another alternative. You can create a copy constructor and overload operator= for MyStruct. In these operations, you need to copy the actual string into the new struct. In C++, structs are nothing more than classes with default public access instead of default private access. Another alternative is to use std::string instead of char* for the string value. C++ strings already have this behavior.
struct MyStruct {
std::string sourceAddress;
int lastSeen;
int beaconReceived;
};
Seems odd to me: Maybe there is something wrong with the //snip part of the code?
Try to log the size of the vector before and after the push_back call (either in the debugger or using cout) and also have a look at the isNewEntry variable.
Your code looks alright to me. Is it possible that you are not passing the right vector in? What I mean is that the behaviour you describe would appear if somehow your Individuals vector is being reset to its orginal 1-entry state before you tried to add the 3rd entry, then it would appear as if your 2nd entry was being overwritten.
Here is what I mean:
int test_table()
{
string SampleAddresses[] = {"Sample Address 1", "Sample Address 2"};
for (int i = 0; i < 2; i++)
{
// All this work to build the table *should* be done outside the loop; but we've accidentally put it inside
// So the 2nd time around we will destroy all the work we did the 1st time
vector<MyStruct> Individuals;
MyStruct Sample;
Sample.sourceAddress = "Sample Address 0";
Test.push_back(Sample);
// this is all we meant to have in the loop
MyStruct NewEntry;
NewEntry.sourceAddress = SampleAddresses[i];
UpdateTable(Individuals, NewEntry);
}
//Now the table has 2 entries - Sample Address 0 and Sample Address 2.
}
If this was all your code then the problem would be obvious. But it might be concealed in some other pieces of code.