данные из ссылки std :: vector становятся поврежденными после возврата из вызова функции - PullRequest
3 голосов
/ 28 июня 2010

У меня есть std::vector< tr1::shared_ptr<mapObject> >, который я пытаюсь собрать из данных, содержащихся в сжатом файле.Вот функция, которую я пытаюсь сделать с помощью:

    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;
        }
    }

Вышеприведенная функция вызывается этим битом кода здесь:

        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;
        }

Когда это выполняется, cerr операторы дают этот вывод (каждый набор выводов имеет ~ 50 строк, поэтому я вырезал большинство для краткости):

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)

У меня, очевидно, есть некоторые неправильные представления о том, как работает shared_ptrs.Я понял, что помещаю копии Tptr в vect, и поэтому все его индексы одинаковы, хотя я думал, что объявление нового shared_ptr в цикле сделает отдельный указатель от других уже вvect, но, думаю, нет.

Понятия не имею, почему набор выходных данных afterCall отличается от набора loadDone (за исключением этого первого значения).В дополнение к (10,1) он также выводит (2274756,134747232) и (134747232, 16), хотя он выводит (10,1) больше, чем любой другой.

Я подозреваю, что моя проблема сводится к неправильному использованию shared_ptr.Может кто-нибудь сказать мне точно, как я это неправильно использую?Учебники, которые я нахожу в Интернете, не очень помогли в этом отношении.

Ответы [ 2 ]

3 голосов
/ 28 июня 2010

Проблема здесь:

     T newT = T::loadType(type, zip);
     Tptr.reset(<b>&newT</b>);

Вы даете shared_ptr указатель на стековую память, которая восстанавливается при возврате функции и больше не действительна.Выделите это из кучи:

shared_ptr<T> Tptr( new T( T::loadType( type, zip )));
0 голосов
/ 28 июня 2010

Я обнаружил тот же дефект в вашем коде, что и Николай, и удалил shared_ptr, который бесполезен:

template<typename T>
void loadSharedPtrVector(std::vector<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();
        vect.push_back(T::loadType(type, zip));
    }
    for(int i=0; i<numT; ++i)
    {
        // outputs the last value pushed onto vect
        std::cerr << "loadDone: " << vect[i].getPosition() << std::endl;
    }
}
...