>我有一个如下所示的地图结构,它shared_pointer了protobuf结构 统计:
map<string, shared_pointer<vol::proto::Stats> statsMap;
我正在通过 LRU 缓存实现存储和检索映射条目
template class LRUCache<string,std::shared_ptr<vol::proto::Stats>>;
原布夫结构式:-
message Stats {
required string oid = 1;
required int64 logical_size = 2;
required int64 committed_size = 3;
}
message StatsRequest {
required string uuid = 1;
}
用于存储地图条目的功能:-
template<class K, class V>
void
LRUCache<K, V>::Put(const K& key, V value)
{
Vmacore::System::WriteSynchronized lock(this);
auto val = refMap.find(key);
if (val == refMap.end()) {
if (cacheSize == refMap.size()) {
K leastUsedKey = lruList.back();
lruList.pop_back();
refMap.erase(leastUsedKey);
}
} else {
lruList.erase(val->second.lruKeyRef);
}
lruList.push_front(key);
refMap[key] = LRUValueReference<K, V>(lruList.begin(), value);
}
void PutS(const string& Id, const vol::proto::Stats& info)
{
shared_ptr<vol::proto::Stats> statsInfo = make_shared<vol::proto::Stats>(info);
_StatsCache.Put(Id, statsInfo);
}
void PutStats(vol::proto::StatsRequest &req) {
vol::proto::Stats *stats;
GetStats(stats); //stats gets populated here.
PutS(stats->oid(), *stats);
}
要从地图获取条目:-
template<class K, class V>
bool
LRUCache<K, V>::Get(const K& key, V& value)
{
Vmacore::System::WriteSynchronized lock(this);
auto val = refMap.find(key);
if (val == refMap.end()) {
return false;
}
lruList.splice(lruList.begin(), lruList, val->second.lruKeyRef);
val->second.lruKeyRef = lruList.begin();
value = val->second.value;
return true;
}
void GetS(const string& Id, shared_ptr<vol::proto::Stats> info)
{
if (!_StatsCache.Get(Id, info))
return false;
return true;
}
void GetStats(vol::proto::StatsRequest &req) {
shared_ptr<vol::proto::Stats> stats;
if (GetS(req.uuid(), stats)) {
Log("object id is %s", stats.get()->oid()); // Crash at oid (this=0x0)
}
}
现在,在执行GetStats时,我在GetStats的日志语句中看到崩溃,该语句的程序以信号SIGSEGV,分段错误终止。 我应该在 GetStats 中对统计数据进行make_share吗?您能否描述一下导致此崩溃的原因以及如何在此处修复崩溃?
您将原始指针从GetStats
传递到GetS
,然后将其包装成shared_ptr
。现在让我们开始引用计数。
- GetS -> 增加进入> 1
- _StatsCache.获取 -> 通过 ref> 1 传递
- 退出时 GetS -> 减少> 0
- 引用计数 0 ->删除指针。
在GetStats
中,您尝试通过调用.get
来取消引用stats
指针,但它刚刚被删除。
您应该始终使用智能指针,或者在从原始指针转换为智能指针并返回时非常非常小心。
实际上我写的是错误的。你正在做的事情实际上要糟糕得多。
您将原始指针包装在GetS
中到智能指针中,然后通过 ref 将其传递给您的_StatsCache.Get
,然后为您的分配不同的shared_ptr
。因此,您已经用其他内容覆盖了原始原始指针。
但是当GetS
返回时,该shared_ptr
现在丢失并被破坏,但原始stats
指针在stats.get()
中被访问。里面有什么?没有来自GetS
,这是肯定的。