Vector General Stack Memory Question

Having a bit of trouble getting a stack based vector implementation up for some reason, having some really really weird memory stuff going on- hoping you can give me a quick hand.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
#include <iostream>

#include <math.h>
#include <functional>

#include "blue_sdl.h"
#include "blue_engine.h"

//<...>

int main(int argc, char* argv[]){

    //<...>

    vector<sprite*> created;
    vecmap<sprite> mp; //basically a 4 way vector

    //<...>

    bool quit=false;event evt;
    while(!quit){

        ng.ren.getscr().clear(col(100,100,100));
        ng.processEvents();

        //<...>

        while(ng.ehnd.get_and_handle_event(evt,"")){
            if (evt.type=="quit"){
                return -1;
            }
            if (evt.type=="keydown"){
                //place a block under player
                if (evt.value=='x'){
                    //get nearest grid position to main character's center
                    icoord cpos(p1.x+p1.sur.width()/2,p1.y+p1.sur.height()/2);
                    icoord gridco = cpos;
                    gridco.x/=32;gridco.y/=32;
                    if (cpos.x<0) gridco.x--;
                    if (cpos.y<0) gridco.y--;

                    //if there isn't currently an object there, go ahead and create it
                    if (mp.getthing(icoord(gridco.x,gridco.y))==NULL){
                        //create on the heap. Doesn't work on the stack??
                        created.push_back(new sprite()); 
                        created.back()->sur.resize(32,32);
                        created.back()->sur.clear(0xff00ffff);
                        created.back()->x=gridco.x*32;
                        created.back()->y=gridco.y*32;
                        mp.setthing(created.back(),icoord(gridco.x,gridco.y));
                        //Same as created.back(), in this case the output is the same in the
                        //upcoming cout that begins with "Previous", however when using the
                        //stack, (vector.push_back(sprite()), the addresses are different?
                        std::cout << "\nCreated " << created[created.size()-1] << " ";
                        std::cout << created.back()->x << "," << created.back()->y << " " 
                        << created.back()->sur.width() << "," << created.back()->sur.height();
                    }
                }
                //<...>
                else if (evt.value=='t'){
                    //simply console out the addresses of the variables in the vector, 
                    //when created on the heap they are different addresses?!?
                    for(int a = 0; a < created.size(); a++){
                        std::cout << "\nPrevious " << created[a] << " ";
                        std::cout << created[a]->x << "," << created[a]->y << " " 
                        << created[a]->sur.width() << "," << created[a]->sur.height();
                    }
                    //double check the addresses in the vecmap, they stay at the originally 
                    //created address when using stack
                    for(int a = 0; a < 20; a++){
                        for(int b = 0; b < 20; b++){
                                
                            icoord gpos = getgridco(coord(a*32,b*32),icoord(32,32));
                            sprite* thng = mp.getthing(gpos);
                        
                            if (thng!=NULL){
                                std::cout << "\nGot " << thng << " ";
                                std::cout << thng->x << "," << thng->y << " " << thng->sur.width() << "," << thng->sur.height();
                            }
                            else{
                                std::cout << ".";
                            }
                        }
                    }
                    std::cout << "\n\n";
                }
            }

            if (evt.type=="up"){if (gridmode){p1.y-=gsize;}else yvel-=acc;}
            if (evt.type=="down"){if (gridmode){p1.y+=gsize;}else yvel+=acc;}
            if (evt.type=="left"){if (gridmode){p1.x-=gsize;}else xvel-=acc;}
            if (evt.type=="right"){if (gridmode){p1.x+=gsize;}else xvel+=acc;}
        }
        //<...>
        ng.regulateFrame();
    }

}


probably unnecessary sprite definition
1
2
3
4
5
6
7
8
9
10
11
12
class sprite{
protected:

public:
    sprite();
    sprite(const sprite& spr); //just calls the = operator, deep copy
    sprite& operator=(const sprite& spr);
    surface sur;
    float x, y;
    //<...>

};


This is fine, it works well. However I have to worry about memory management, and will end up creating a class to deal with it- I've had this problem before, and didn't have the wherewithall to ask smarter people about it.

So here we go:

vector<object> objlist; vector<object*> objpoints;

to add to objpoints I can objpoints.push_back(new object());
to add to objlist I can objlist.push_back(object());

In the second case, I'm guessing the the temporary object falls out of scope as soon as the push_back is called, and ends up corrupting memory by trying to copy from that position with object's copy constructor? If I want to allocate something on the stack, is there a way to do it inline like this or should I instead call resize and let the vector take care of it? Or am I instead off the mark, and maybe I have my object definition wonky?

Also the preview button seems broken And it did some damage to my formatting :(
Last edited on
objpoints.push_back(object());
I don't believe this is possible because object is not a pointer.

Also I would recommend for you to use shared_ptr instead of raw pointers because you have to delete the object that your pointer is pointing to before you can delete the pointer every time.

Also i believe that vectors elements are only in heap, and when you use pointers, it is just a heap of pointers.
Oops, good call, fixed to objlist instead of objpoints, which I'm pretty sure is possible because it makes a copy of the temporary object?
Before I answer your question directly, allow me to interrupt:

1
2
3
vector<object*> objpoints;
[snip]
objpoints.push_back(new object());


I do not recommend this, because now you can't remove elements from that vector without deleting them first. Which also means you have to have a dtor in whatever class own that vector, and you have to manually delete each item.

General rule of thumb: if you are manually deleting, you are doing something wrong.
Another general rule of thumb: if you are using new, whatever you're new'ing should be going directly into a smart pointer.

A better approach:
1
2
3
vector<unique_ptr<object>> objpoints;

objpoints.emplace_back( new object() );


Since you have a vector of smart pointers, they will be automatically deleted when the vector is destroyed, or when individual elements are removed. With this, there is practically 0 risk of memory leaks.



As for your actual question...


to add to objlist I can objpoints.push_back(object());

In the [above] case, I'm guessing the the temporary object falls out of scope as soon as the push_back is called, and ends up corrupting memory by trying to copy from that position with object's copy constructor?


No. The above call will work exactly how you expect.

1) Temporary object is constructed
2) Copy ctor called to put that temporary object into the vector
3) Temporary destroyed

or... with optimizations enabled ... what is more likely is that the compiler will optimize the temporary/copy away, and simply put the object into the vector directly.

Either way the code will do what you want and work correctly. The only way it wouldn't is if your object class does not copy itself correctly or if you rely on the 'this' pointer somehow.


If I want to allocate something on the stack,


If it's in a vector, it's on the heap. If it's dynamically allocated, it's on the heap.

"On the stack" basically equates to "declared locally in a function":

1
2
3
4
5
6
7
void func()
{
    int foo = 5;  // foo is on the stack
    vector<int> woo;  // woo is on the stack

    woo.push_back(foo); // inside the vector, a copy of foo is made on the HEAP
}


Note this might not always be 100% true as it depends on the implementation of vector.... but generally speaking.

Though whether or not something is on the stack typically doesn't matter.
Last edited on
Disch wrote:
No. The above call will work exactly how you expect.


How interesting, I'll spend some more time figuring out where the disconnect is. Be back in an hour or so to check in.
Disch, I'm not sure if I'm right, but shouldn't he be using a shared_ptr instead of an unique_ptr because I believe he copies the pointer in the call (line 50):
mp.setthing(created.back(),icoord(gridco.x,gridco.y));

And that unique_ptrs can't be copied.

Plus if you could use a unique_ptr in a vector, I would use boost's ptr_vector.
Disch, I'm not sure if I'm right, but shouldn't he be using a shared_ptr instead of an unique_ptr because I believe he copies the pointer in the call (line 50):


Well he'd have to change that line then. =P

Generally speaking, shared_ptr is for shared ownership. And shared ownership is not always the best idea. It's usually best to have 1 clear owner for allocated memory, even when using smart pointers.

Plus if you could use a unique_ptr in a vector, I would use boost's ptr_vector.


That'd have the same effect, sure, but would require boost as an additional dependency, for no actual gain.
That'd have the same effect, sure, but would require boost as an additional dependency, for no actual gain.

Dude, boost has so many features, why would anyone not already have boost unless if they hate it.
Topic archived. No new replies allowed.