1

当使用 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 字段”

4

1 回答 1

1

好的,我不太了解您的代码,但简短的回答: - 游标返回的数据在下一次迭代或游标被破坏时失效。使用“ getOwned() ”获得 BSONObj 对象的副本:

 cursor->next().getOwned(); 
于 2014-03-26T13:41:49.380 回答