Mmm Donuts
Mmm Donuts

Reputation: 10285

Multiple New Objects Have The Same Pointer Addresses

I'm relatively new to C++ so I apologize right away if this is a stupid question but I can't for the life of me seem to figure out whats going on. Essentially, I enter a helper function that creates objects, and then returns a pointer to each object. Its works okay, but the issue that is popping up is that sometimes, the pointer values are identical to the last iteration of the function call.

For example:

I'll often see something ...

0x7fff5d1d0f10
0x7fff5d1d0d80
0x7fff5d1d0d80 <- same as the last pointer
0x7fff5d1d0fe0
0x7fff5d1d0fe0 <- same as the last pointer

Is this undefined behaviour? I would very, very much appreciate any and all help!

The pointers are the return values of this helper function (sorry its a bit verbose):

w5::iMessage* w5::getMessage(std::ifstream& file, char limiter){

    std::string result;

    int line_no = 0;

    std::string line;
    while (getline(file, line)){
        if(line[0] == 'T' or line[0] == 'e'){
            iMessage * message;
            message = nullptr;
            std::string user = "";
            std::string reply = "";
            std::string tweet = "";

            if (line[0] == 'T'){
                int length = line.length();
                int _user = line.find("T");
                int _reply = line.find("@");
                if(_reply != std::string::npos){
                    int first_space = line.find_first_of(" ");
                    int second_space = line.find_first_of(" ", _reply);
                    //user
                    //std::cout << line.substr(_user+1, _reply-2) << std::endl;
                    user = line.substr(_user+1, _reply-2);
                    //reply
                    // std::cout << line.substr(_reply+1, second_space-_reply)  << std::endl;
                    reply = line.substr(_reply+1, second_space-_reply);
                    //tweet
                    //std::cout << line.substr(second_space+1)  << std::endl;
                    tweet = line.substr(second_space+1);
                    Twitter twitter(user, tweet, reply);
                    // std::cout << &twitter << std::endl;
                    message = &twitter;
                    // std::cout << message << std::endl;
                    return message;

                }else{
                    int _tweet = line.find(" ");

                    //user
                    //std::cout << line.substr(_user+1, _tweet) << std::endl;
                    std::string user = line.substr(_user+1, _tweet);

                    //tweet
                    if(_tweet != std::string::npos){
                        // std::cout << line.substr(_tweet+1)  << std::endl;
                        std::string tweet = line.substr(_tweet+1);
                        if(tweet != ""){
                            Twitter twitter(user, tweet, "");
                            iMessage * message;
                            // std::cout << &twitter << std::endl;
                            message = &twitter;
                            // std::cout << message << std::endl;
                            return message;
                        }
                    }
                }


            }

            if(line[0] == 'e'){
                int length = line.length();
                int _from = line.find("From:");
                int _to = line.find(" To:");
                int _date = line.find(" Date:");
                int _body = line.find(" Body:");
                std::string to = "";
                std::string from = "";
                std::string date = "";
                std::string body = "";
                //from
                //std::cout << line.substr(_from+5, _to-_from-4) << std::endl;
                to = line.substr(_from+5, _to-_from-4);
                //to
                // std::cout << line.substr(_to+4, _date-_to-3) << std::endl;
                from = line.substr(_to+4, _date-_to-3);
                //date
                // std::cout << line.substr(_date+6, _body-_date-6) << std::endl;
                date = line.substr(_date+6, _body-_date-6);
                //body
                // std::cout << line.substr(_body+6) << std::endl;
                body = line.substr(_body+6);
                Email email(from, to, body, date);
                // std::cout << &email << std::endl;
                message = &email;
                // std::cout << message << std::endl;
                return message;
            }

            result += line + "\n";
            line_no++;
        }
    }

    iMessage *message;
    message = nullptr;
    return message;

}

The problems exist at these lines:

        Email email(from, to, body, date);
        // std::cout << &email << std::endl;
        message = &email;
        // std::cout << message << std::endl;
        return message;

For some reason the pointer value of &email seems to be the same as the last iteration instead being a new pointer value. The same issue exists in the other return points of the function.

'iMessage message' is an abstract base class.

Upvotes: 0

Views: 1854

Answers (1)

Len Holgate
Len Holgate

Reputation: 21616

You are creating your objects on the stack and returning them. This is a bad thing to do as the object on the stack will a) be destroyed when the scope in which it is created is left and b) the memory that you're returning isn't yours to return.

You need to allocate the objects to return on the heap and return them by pointer and then clean them up when you are done with them. You may wish to consider returning some kind of smart pointer to manage the lifetime of the dynamic memory that you're allocating.

So, instead of

    Email email(from, to, body, date);
    // std::cout << &email << std::endl;
    message = &email;
    // std::cout << message << std::endl;
    return message;

You want to do this:

    message = new Email(from, to, body, date);

    return message;

The reason that your current implementation sometimes displays the same memory addresses is simply because the objects happen to be being created in the same place on the stack. The bug is that you're returning pointers to these stack based objects rather than allocating on the heap and returning an object that can outlive the function call.

Upvotes: 3

Related Questions