作者热门文章
- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我有以下 C++ 代码,它由网络服务器通过 JNI 调用。
static shared_ptr<multimap<string,SomeObject> > cacheMap;
void Cache::refresh(multimap<string, SomeObject> delta){
shared_ptr<multimap<string, SomeObject> > old_cache=atomic_exchange(&cacheMap,make_shared<multimap<string,SomeObject> >(delta));
shared_ptr<multimap<string, SomeObject> > old_readMap=atomic_load(&old_cache);
if(old_readMap){
for(std::multimap<string, SomeObject>::iterator it = old_readMap->begin(); it != old_readMap->end(); it++){
it->second.getSomeObject()->~SomeObject();
}
old_readMap->clear();
}
}
list<int> Cache::get(string key1,const char* key2){
SomeObject value;
list<int> IDs;
try{
shared_ptr<multimap<string,SomeObject> > readMap=atomic_load(&cacheMap);
pair<mapIterator,mapIterator> result=readMap->equal_range(key1);
for(auto iterator=result.first; iterator!=result.second; iterator++){
value=iterator->second;
if(!(value.getSomeObject()->test(key2,strlen(key2)))){
IDs.push_front(value.getInternalID());
}
}
}
catch(...){
std::exception_ptr p = std::current_exception();
std::clog <<(p ? p.__cxa_exception_type()->name() : "null") << " from Cache.cpp " << std::endl;
}
return IDs;
}
cacheMap 将由 cronjob 每 5 分钟刷新一次,请求线程通过 get() 不断访问缓存。这是一个多线程环境。一切正常,3 或 4 天后,我收到此 SEGV_ACCER/SEGV_MAPPER 错误,转储如下所示(转储中的几行)
# Problematic frame:
# C [libstdc++.so.6+0xd7172] std::string::assign(std::string const&)+0x12
...
Stack: [0x00007fed854c2000,0x00007fed855c3000], sp=0x00007fed855c08b0, free space=1018k
Native frames: (J=compiled Java code, j=interpreted, Vv=VM code, C=native code)
C [libstdc++.so.6+0xd7172] std::string::assign(std::string const&)+0x12
C [libCustomCache.so+0x1c0b0] Cache::get(std::string, char const*)+0x122
我已经使用shared_ptr
和原子操作来保证线程安全,但仍然出现这个错误。关于如何调试这个的任何想法?
最佳答案
Cache::refresh
和 Cache::get
竞相同时销毁和读取同一个 SomeObject
对象。这是一种竞争条件。
std::shared_ptr
的原子指针或原子用法在这里仅使指针的值成为原子的和无竞争的,而不是指针所指的对象。
一种可靠的方法是使用 C++17 std::shared_mutex
或 C++14 boost::shared_mutex允许读者并发访问缓存,而只允许作者独占访问。
您还应该消除手动销毁 SomeObject
的需要。
例子:
using namespace std;
namespace {
shared_mutex m;
multimap<string, SomeObject> cacheMap; // SomeObject doesn't need to be manually destroyed.
} // namespace
void Cache::refresh(multimap<string, SomeObject> delta){
std::unique_lock lock(m); // Writer exclusive lock.
cacheMap = std::move(delta);
}
list<int> Cache::get(string const& key1, const char* key2) {
list<int> IDs;
std::shared_lock lock(m); // Readers shared lock.
for(auto result = readMap->equal_range(key1); result.first != result.second; ++result.first) {
auto&& value = *result.first;
if(!(value.getSomeObject()->test(key2, strlen(key2))))
IDs.push_front(value.getInternalID());
}
return IDs;
}
关于c++ - 有时只会出现 jni segv_accer 或 segv_mapper 错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58400915/
我有以下 C++ 代码,它由网络服务器通过 JNI 调用。 static shared_ptr > cacheMap; void Cache::refresh(multimap delta){
我是一名优秀的程序员,十分优秀!