从函数调用返回后,来自std :: vector引用的数据会损坏

时间:2010-06-27 22:56:16

标签: c++ shared-ptr

我有一个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 个答案:

答案 0 :(得分:3)

问题在于:

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

你给堆栈内存shared_ptr指针,它在函数返回时回收并且不再有效。从堆中分配:

shared_ptr<T> Tptr( new T( T::loadType( type, zip )));

答案 1 :(得分:0)

我在代码中发现了与Nikolai相同的缺陷,并删除了无用的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;
    }
}