MongoDB C ++ BSONObj生命周期

时间:2013-10-28 15:07:00

标签: c++ mongodb

当使用C ++客户端库并保留从cursor-> next()返回的BSONObj对象时,后续的新查询(使用相同的连接)会以某种方式破坏该对象吗?我的理解是它是一个智能指针,并将一直存活,直到最后一次引用超出范围。然而,实践告诉我,后续查询似乎会破坏对象。在遍历新查询后访问对象的hasField / getField方法时出现分段错误。

以下是相关代码:

BSONObj DB::getmsg        
(                         
    const string &oid     
)                         
{                         
    BSONObj query = BSON("_id" << OID(oid));
    auto_ptr<DBClientCursor> cursor = c.query("nsdb.messages", query);
    if (cursor->more())                                               
        return cursor->next();                                        
    throw Exception("could not find object %s", oid.c_str());         
}                                                                     

void DB::getchildren
(                   
    const string &oid,
    vector<BSONObj> &children
)                            
{                            
    BSONObj query = BSON("parent" << oid);
    BSONObj fields = BSON("_id" << 1);    
    auto_ptr<DBClientCursor> cursor =     
        c.query("nsdb.messages", query, 0, 0, &fields);
    while (cursor->more())                             
        children.push_back(cursor->next());            
}                                                      

void DB::message
(               
    const string &oid,
    string &str,      
    bool body         
)                     
{                     
    connect();        
    BSONObjBuilder response;
    try                     
    {                       
        BSONObj n = getmsg(oid);
        response.append("message", n);
        vector<BSONObj> children;     
        getchildren(oid, children);   
        if (children.size() > 0)      
        {                             
            BSONArrayBuilder a;       
            vector<BSONObj>::iterator i;
            for (i = children.begin(); i != children.end(); i++)
            {                                                   
                if (!(*i).isEmpty() && (*i).hasField("_id"))    
                {                                               
                    string child = (*i).getField("_id").__oid().str();
                    a.append("http://127.0.0.1:12356/lts/message/" + child);
                }                                                           
            }                                                               
            if (a.len() > 0)
                response.append("children", a.done());
        }
        if (body)
        {
            string fname;
            if (n.hasField("fname"))
                fname = n.getField("fname").str();
            if (fname.empty())
            {
                throw Exception("no fname field in message record %s",
                    n.jsonString().c_str());
            }
            auto_mmapR<const void *, int> m(fname);
            response.appendBinData("body", m.size(), BinDataGeneral,
                m.get());
        }
        str = response.obj().jsonString();
    }
    catch (const DBException &x)
    {
        throw Exception("%s", x.what());
    }
}

如果我移动部件:

string fname;
if (n.hasField("fname"))
    fname = n.getField("fname").str();

在调用getchildren(...)之前的某个位置,然后从消息中正确检索fname字段,否则抛出异常'消息记录中没有fname字段'

1 个答案:

答案 0 :(得分:1)

好的,我没有太多了解你的代码,但简短的回答:   - 游标返回的数据在下一次迭代或光标被销毁时无效。 使用“ getOwned()”获得BSONObj对象的副本:

 cursor->next().getOwned();