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