For some reason when I try and read a property of a pointer to an object(GamePlayer) within an std::list (playerlist) it works at first, but when I try to access it later in another function I get a bunch of random numbers instead of the numbers for my client's socket. That was a mouthful, sorry. I hope someone could shed some light on the situation. I will include a simplified version of the defective code.
class GameRoom {
list<GamePlayer*> playerlist;
locigPort( LogicObj );
}
bool GameRoom::logicPort( LogicObj logit ) { // This is room[1]
list<GamePlayer*>::iterator it;
for (it = playerlist.begin(); it != playerlist.end(); it++){
cout << "socket numbers " << (*it)->socketno << endl;
/* (*it)->socketno gives me a bunch of random numbers,
not the socket numbers I was looking for! */
}
return true;
}
bool RoomDB::addPlayer( GamePlayer *playerpoint ) {
roomlist[1].playerlist.push_back( playerpoint );
// This adds the player object to the Gameroom object
cout << "player point " << playerpoint->socketno << " roomno: " << roomno;
// This shows everything should be ok so far
return true;
}
The most likely explanation is that you're calling addPlayer with a pointer than becomes invalid by the time you call logicPort. One possibility is that you call addPlayer with the address of an object on the stack, and the object disappears when the stack is unwound.
edit The problem is right here:
bool PlayerDB::addPlayer( int sid, GamePlayer tempplayer ) {
...
roomman.addPlayer( &tempplayer, tempplayer.roomno );
}
PlayerDB::addPlayer takes the second argument by value. This means that it gets a copy that exists for the lifetime of the method. You then take the pointer to that copy, and add it to the list. Once PlayerDB::addPlayer returns, the pointer becomes invalid.
It's hard to suggest a good fix without seeing more code. One possibility is to make PlayerDB::addPlayer take a pointer as its second argument, and make sure you don't repeat the same mistake one level up the call chain.
An even better possibility is to turn playerlist into list<GamePlayer>: from your code there doesn't appear to be any need for the list to contain pointers. This will simplify things greatly.
Related
Firstly please have a look at some simple codes that my questions derived from.
#include <iostream>
#include <string>
using namespace std;
string get_something()
{
cout << "output something";
return " and return something";
}
void print_something()
{
cout << "print something";
}
int main()
{
cout << get_something(); // will work
cout << print_something(); // will NOT work
return 0;
}
The only different thing I notice between get_something() and print_something() is that one is a return type and one isn't. As you can see I have added comments indicating that which one will work and not work.
However, I am really not sure what is happening behind the scene that makes it one possible and the other not possible.
I am not even sure how I should go about and search for this kind of question too.. so here I am asking a question.
Please enlighten me..
edit:
I am confused that how it is possible to do cout after cout..
both of the functions do that but one of them works and the other doesn't.
This seems to be a very common misunderstanding among beginners. Printing something via cout is not the same as returning a value from a function. Thats completely orthogonal things.
You can write:
std::string returned_value = get_something();
std::cout << returned_value;
But you cannot write:
??? returned_value = print_something();
std::cout << returned_value;
because print_something() does not return anything! void denotes the absence of a type. You cannot have an object of type void.
On the other hand, when you call a function, you can use the returned value (above), or you can ignore it, so this is correct code:
print_something(); // prints something
get_something(); // also print something and returned value is ignored
Note that the function get_something should get a better name, because it is not just "getting" a value. How about print_and_return_something()?
PS:
What I am really confused about is that, how is it possible to do a cout after a cout? Am I just missing what cout actually does?
Not sure If I understand, but I will try... std::cout is an object of type std::ostream. It has an operator<< that you can call, similar to calling methods of other objects. The following two are identical and just use different syntax:
std::cout.operator<<( "Hello World");
std::cout << "Hello World";
When you call print_something() then first the function is executed, then the return value is returned to the caller and execution continues with the caller. This:
std::cout << get_something();
is more or less the same as (well, its a crude simplification, but should be ok here):
// inside get_something
std::cout << "output something";
// return value
std::string result{"output something"};
// now execution continues in caller
std::cout << result;
Calling cout after cout is no different from calling some other function. Suppose you have a function print() that prints something then you can write
std::string print_and_return() {
std::string x{"Hello World"};
print(x);
return x;
}
The caller can do
std::string x = print_and_return(); // <- this already calls print()
print(x); // now we call it again
This is more or less the same as yours, just that I used some hypothetical print() instead of std::cout::operator<<.
Both your functions have a return type. It's just that one of them has a void return type.
The std::ostream class does not have an overload for << that takes a void type. This is sensible - what would be written to the stream in that case?
(cout is an instance of std::ostream that typically writes itself to the standard output which is normally the shell you're using to launch the program.)
Because print_something() has nothing to return, and cout want something to write to the console (the return value it is expecting). Therefore, it will give error.
get_something(), on the other hand, has something to return. So after executing it's rest of line (except return statement) it return the string, which gets printed by cout
get_something() returns something (what seems to be accepted by cout), so cout will receive the returned thing and will work.
On the other hand, print_something() returns nothing (because its return type is void), so cout cannot receive anything to print and won't work.
cout is a stream object.and we use << (insertion operator) to insert value like String,float,Int etc to it which will be displayed in output Screen.Since print_something() is not returning any value so nothing is inserted in stream ,That's why it is not working.
I recommend you to read about Streams in c++ ..
I've been delving into the referenciation and smart pointers over the last couple of days and I still can't figure out when to use which.
Especially for the very simple program I am trying to write.
Where the object value shouldn't be shared but only modified trought returning a value of its type from X or Y methods.
If I am not mistaken, references are easier on the memory, but refers only to one thing.
Where as smart pointers are more stable and can be remaped to point at something else.
First Question:
For simple alterations to an object like in the example bellow, is it even necessary to create a reference or a pointer?
I suppose that in the long run, as the program adds in complexity, having but initialized objects doing their thing could create latency issues and the likes...
Second Question:
As I understand it, refering to an object will aleviate the stress on the memory by refering to the object when used as a parameter in the method instead of copy-pasting the object into it?
Does a smart_ptr does the same-ish?
The header file for class:
-Items.h-
class Health_Potion
{
public:
int qty = 0;
static int add_health_potion(int current, int add);
};
The cpp file for methods:
-Items.cpp-
int Health_Potion::add_health_potion(int current, int add)
{
int new_current = current + add;
cout << add << " potion added to your inventory.\n";
cout << "Quantity available: " << new_current << "\n";
return current + add;
}
The main function:
-Main-
int main()
{
// Initializing the method to be used:
// Question: Should this also be stored into a smart_ptr or referenced to?
Health_Potion add_method;
add_method.add_health_potion;
______________________________________________
// The unique_ptr version I got:
std::unique_ptr<Health_Potion> entity(new Health_Potion); //Unique_ptr
entity -> qty = add_method.add_health_potion(rentity -> qty, roll); //returning new value to the pointer through method
______________________________________________
//The reference version I got:
Health_Potion obj1;
int & refqty = obj1.qty; //reference to object of qty created
refqty = add_method.add_health_potion(refqty, roll); //returning new value to the reference through method
}
Forgive my newbieness.
And thank your for your time :).
I still can't figure out when to use which.
When in doubt, use the simplest approach. Only when the simplest approach is inadequate or awkward is there a reason to consider something more complicated (and at that point, you have a starting point for figuring out which to use).
In my program, I'm trying to dereference a pointer to a struct Article, to get its id, but I'm getting "Access violation reading location 0xCCCCCCCC". I've tried many different things, local variables, backtracking the pointers back into the code, different parentheses... nothing though. I'm out of options and I can't see the problem however hard I try.
There might be an answer to this question, but access violation is much too general for me to be able to find the answer I'm looking for (also most of the questions go around arrays, which aren't my case).
Here I define a simple struct to keep my data.
struct Article {
public:
std::string id;
std::string title;
std::string text;
Article(std::string article_id, std::string article_title, std::string article_text) : id(article_id), title(article_title), text(article_text) {};
void toString();
};
Next, I use a dictionary that maps all words to the articles where they appear. The code is not done itself, but maps of words should include all the necessary pointers.
std::map<std::string, std::map<Article*, unsigned>> word_dict_;
I also keep another vector<Article> articles_ wher I keep all of them, so no null pointers should appear in the word_dict_;
Here the dictionary gets generated.
void fulltext::generateDict() {
for (Article ar : articles_) {
unsigned wordStart;
bool isBuilding = false;
string buffer = "";
for (unsigned int it = 0; it <= ar.text.size(); ++it) {
char c;
if (it < ar.text.size())
c = ar.text.at(it);
else
c = '\0';
if (isalpha(c)) {
// start or middle of word
if (!isBuilding) {
isBuilding = true;
wordStart = it;
}
buffer += c;
}
else {
isBuilding = false;
if (buffer != "") {
stringToLower(buffer); // rewrites buffer to low case
// Here I tried creating &ar just for the laughs and it works just fine.
word_dict_[buffer][&ar] = wordStart;
buffer = "";
}
}
}
}
}
Last but not least, I want to have it printed out and here the real fun starts.
void fulltext::printWordDict() {
cout << "Printing generated word dictionary: " << endl;
for (auto wordPair : word_dict_) {
cout << " \" " << wordPair.first << " \" " << endl;
cout << "There are " << wordPair.second.size() << " inputs." << endl;
for (pair<Article*, unsigned int> articlePair : wordPair.second) {
cout << (articlePair.first)->id << endl; // Here the access violation occurs
// Nothing seemingly works
// cout << articlePair.first->id; ... Access violation
// cout << (*articlePair.first).id; ... Access violation
// auto ar = articlePair.first; cout << ar->id; ... access violation
// auto ar = articlePair.first; cout << (*ar).id; ... access again
}
cout << endl;
}
cout << "Done." << endl;
}
These functions are called from within a main function fulltext::proccess() coincidentally in immediate succession. The word_dict_ is class private variable.
If there's need for any other parts of the code, just let me know, although none of the others should make any issues in this case.
for (Article ar : articles_) {
...
word_dict_[buffer][&ar] = wordStart;
...
}
Here you are storing a pointer to ar in your dictionary, however ar is destroyed at the end of its scope - when your for loop ends. So now you are storing a dangling pointer in your map, which you cannot de-reference.
Store Article objects in your map instead of Article* , or otherwise ensure the Article object lives somewhere as long as you have a pointer to it in your map.
If you have the objects live in your articles_ container, you might not need to copy it in your for loop, and instead do:
for (Article& ar : articles_) {
..
word_dict_[buffer][&ar] = wordStart;
Now you'll get a pointer to your Article object that resides within article_.
Though be aware what you do with article_ later on - if you perform operations on it that moves objects around (which can happen for many reasons depending on the container type), your pointers within word_dict_ becomes invalid.
for (Article ar : articles_)
This performs a copy of your article, as a local variable. This local variable goes out of scope as soon as the next iteration of the loop rolls around.
word_dict_[buffer][&ar] = wordStart;
Here you store a pointer to the local variable, that is valid only inside your loop.
If you can ensure that your articles will outlive your map, you can store a pointer to the articles stored in articles_. Take note, that if articles_ is a std::vector, it might get reallocated when you insert new articles into it, so storing pointers to object inside it has to be done carefully, making sure to invalidate them when the std::vector changes.
If all of the above sounds like your cup of tea, You most probably want to create a reference to the article, like so
for (Article& ar : articles_)
If the above sounds a bit too complicated, you have 2 possible approaches.
Make your word_dict_ map store Article objects by Value, instead of as pointers. Downside of this approach is that you store your articles twice, which has logical implications (changes to the article inside your map won't be reflected in the articles_ vector and vice-versa) as well as memory implications (you use double the memory)
Make your articles_ vector store std::unique_ptr<Article>. This way, you won't need to manually manage the reallocations inside your vector. You will still need to manage the case where an Article is removed from the articles_ vector, and make sure to remove it from the word_dict_ map. The downside of this approach is that it makes your class uncopiable by default (std::unique_ptr has a deleted copy constructor), which might or might not be a problem for you. If you need them to be copied, you would need to manually provide a copy ctor and copy assignment operator, as well manually implement or = default the other 3 special member functions (see Rule of 5)
I have a simple function that I simplified to return just a dummy list (to ensure its not some logic error)
vector<AttrValue>* QueryEvaluator::getCandidateList(...) {
...
values.clear();
values.push_back(2);
values.push_back(3);
cout << "values is of size " << values.size() << endl;
return &values;
}
then in a cppunit test:
vector<AttrValue>* candidateList0 = evaluator->getCandidateList(cl, 0);
cout << candidateList0->size() << endl;
But problem is size(), in the test, is always 0 even though the cout message prints the correct size 2. What might be wrong?
I tried a simple program and it appears to be fine ...
#include <iostream>
#include <vector>
using namespace std;
vector<int>* test() {
vector<int> vec { 2, 3, 6, 1, 2, 3 };
return &vec;
}
int main() {
cout << test()->size() << endl;
return 0;
}
You are returning a the address of temporary from getCandidateList function, the object is release when function returns. access to it is undefined behavior. You could just return the vector out, RVO should come to apply and elide the copy:
Try:
std::vector<AttrValue> QueryEvaluator::getCandidateList(...)
{
//blah
return values;
}
I tried a simple program and it appears to be fine ...
the temporary vector is released when getCandidateList function returns. The program has undefined behavior.
Your vector appears to be declared on the stack so will be destroyed when it goes out of scope (when the function exits). If you want to return a pointer to a vector, allocate it on the heap instead
vector<AttrValue>* QueryEvaluator::getCandidateList(...) {
vector<AttrValue>* values = new vector<AttrValue>();
...
values->clear();
values->push_back(2);
values->push_back(3);
cout << "values is of size " << values->size() << endl;
return values;
}
It might be easier to instead declare it in the caller and pass a reference to getCandidateList
void QueryEvaluator::getCandidateList(vector<AttrValue>& values)
...or return it by value
vector<AttrValue> QueryEvaluator::getCandidateList(...) {
So many interesting things to consider:
vector<AttrValue>* QueryEvaluator::getCandidateList(...) {
...
values.clear();
values.push_back(2);
values.push_back(3);
cout << "values is of size " << values.size() << endl;
return &values;
}
So it looks like you left out the most interesting piece in the code ... above. Moral of the story try and provide compilable working code that shows the error. Reducing your problem to a small example usually results in you finding the problem yourself. At the very least you should provide exact definitions of all objects that are used (the type is the most important thing in C++)
Does it declare the vector as a local object?
std::vector<int> values;
In this case the vectors lifespan is bound to the function and it is destroyed at the end of the function. This means using it after the function has returned is undefined behavior (anything can happen).
But it also looks like you are using objects as part of you unit test framework. So a potential solution is to make the vector part of the object. Then the vector will live as long as the object (not just the function call) and thus returning a pointer to it will work as expected.
class QueryEvaluator
{
std::vector<int> values;
public:
vector<AttrValue>* QueryEvaluator::getCandidateList(...);
};
An alternative would be to return the vector by value rather than a pointer. This means the object will be correctly copied out of the function and your calling code can manipulate and test the vector all they need.
vector<AttrValue> QueryEvaluator::getCandidateList(...)
{
...
return &values;
}
Side Note:
Also you need to try not to use pointers in your code. Pointers doe not convey any ownership.This means we do not know who is responsible for deleting the object. In this case a reference would probably have been better (you never return NULL) as this gives the caller access to the object will retaining ownership (assuming you decided not to return by value).
I'm trying to make it so I have one object, that has a pointer, so multiple classes can work with the same object. But the only thing it's giving me is 1 instead of the hexadecimal address that I need.
My code:
code to create it:
SDL_Event event;
EventHandler eh(&event);
code using it:
EventHandler::EventHandler(SDL_Event* eventpointer)
{
EventHandler::event = eventpointer;
//This code is to test the pointer:
std::cout << &EventHandler::event << std::endl;
}
output:
1
Process returned 0 (0x0) execution time : 0.092 s
Try printing the value of event, not the address of it:
std::cout << EventHandler::event << std::endl;
There are actually several unusual things about your testcase. Correcting all of them, I end up with this:
EventHandler::EventHandler(SDL_Event* eventpointer) : event(eventpointer)
{
//This code is to test the pointer:
std::cout << event << "\n";
}
The things I changed are:
Prefer initialization lists to assigning values in constructor bodies
Print value of event variable not its address. The value of event is the same as the value of eventpointer, which is the same as the address of the original SDL_Event object.
Avoid the scope qualifier. Inside the class's functions, you may refer to members simply by name.
Aside: I'm going to answer the actual question in an aside since it turns out to be irrelevant to the author's true intent. The actual reason he sees 1 instead of a pointer value is this: he is trying to print the value of a pointer-to-member. operator<< has no overload which takes a pointer-to-member, so it converts it to bool instead. His expression is non-null, so the conversion results in true, which is printed as 1.