Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

data from a std::vector reference becomes corrupt after return from function call

Tags:

c++

shared-ptr

I have a std::vector< tr1::shared_ptr<mapObject> > that I'm trying build from data contained in a compressed file. Here's the function I'm attempting to do that with:

    using std::tr1::shared_ptr;

    template<typename T>
    void loadSharedPtrVector(std::vector< shared_ptr<T> >& vect, TCODZip& zip)
    // the TCODZip is the compression buffer I'm loading the data from.  It's
    // working correctly and isn't really part of this problem.
    {
        vect.clear();

        // load the size of the saved vector
        int numT = zip.getInt();

        // load the saved vector            
        for(int i=0; i<numT; ++i)
        {
            int type = zip.getInt();
            shared_ptr<T> Tptr(new T);
            T newT = T::loadType(type, zip);                
            Tptr.reset(&newT);
            std::cerr << "load: " << Tptr->getPosition() << std::endl; // outputs correct values
            vect.push_back(Tptr);
        }
        for(int i=0; i<numT; ++i)
        {
            // outputs the last value pushed onto vect
            std::cerr << "loadDone: " << vect[i]->getPosition() << std::endl;
        }
    }

The above function is called by this bit of code here:

        typedef std::tr1::shared_ptr<mapObject> featurePtr;

        // 'features' is a std::vector<featurePtr>, 'zip' is a TCODZip previously declared
        utility::loadSharedPtrVector<mapObject>(features, zip);

        vector<featurePtr>::const_iterator fit;
        for(fit=features.begin(); fit<features.end(); ++fit) 
        {
            // outputs mostly garbage
            cerr << "afterCall: " << (*fit)->getPosition() << endl;
        }

When this is run, the cerr statements give this output (each set of output has ~50 lines, so I cut out most for brevity):

load: (5,40)
load: (5,45)
load: (5,58)
(etc.  all 'load' lines are correct output)
load: (87,68)
load: (11,5)
loadDone: (11,5)
loadDone: (11,5)
loadDone: (11,5)
loadDone: (11,5)
loadDone: (11,5)
loadDone: (11,5)
(etc. all 'loadDone' lines are the same)
afterCall: (11,5)
afterCall: (10,1)
afterCall: (10,1)
afterCall: (10,1)
afterCall: (10,1)
afterCall: (10,1)
afterCall: (10,1)
(etc. all 'afterCall' lines are the same except for the first)

I apparently have some misconceptions about how shared_ptrs work. I realized that I'm pushing copies of Tptr into vect, and that's why all of its indices are the same, although I thought that declaring a new shared_ptr in the loop would make a separate pointer from the other ones already in vect, but I guess not.

I have no idea why the 'afterCall' set of output is different from the 'loadDone' set (except for that first value). In addition to (10,1) it has also output (2274756,134747232) and (134747232, 16), although it outputs (10,1) more than any other.

I suspect that my problem boils down to my misuse of shared_ptr. Can anyone tell me exactly how I'm misusing it? The tutorials I find online haven't been very helpful in this regard.

like image 655
Max Avatar asked Sep 23 '26 05:09

Max


1 Answers

The problem is here:

     T newT = T::loadType(type, zip);
     Tptr.reset(&newT);

You give shared_ptr pointer to stack memory, which is reclaimed at function return and is no longer valid. Allocate that from the heap:

shared_ptr<T> Tptr( new T( T::loadType( type, zip )));
like image 111
Nikolai Fetissov Avatar answered Sep 24 '26 23:09

Nikolai Fetissov



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!