繁体   English   中英

使用parallel_unordered_map崩溃

[英]Crash using concurrent_unordered_map

我有一个concurrent_unordered_map 我使用insert功能(没有其他功能)尝试同时插入地图。 但是,很多时候,这会在insert函数内部深处崩溃。 这是一些代码:

class ModuleBase { 
public:
    virtual Wide::Parser::AST* GetAST() = 0;
    virtual ~ModuleBase() {} 
};
struct ModuleContents {
    ModuleContents() {}
    ModuleContents(ModuleContents&& other)
        : access(other.access)
        , base(std::move(other.base)) {}
    Accessibility access;
    std::unique_ptr<ModuleBase> base;
};
class Module : public ModuleBase {
public:
    // Follows Single Static Assignment form. Once it's been written, do not write again. 
    Concurrency::samples::concurrent_unordered_map<Unicode::String, ModuleContents> contents;
    Wide::Parser::AST* GetAST() { return AST; }
    Wide::Parser::NamespaceAST* AST;
};

这是我实际插入地图时使用的功能。 还有更多,但它不会触及地图,仅使用insert的返回值。

void CollateModule(Parser::NamespaceAST* module, Module& root, Accessibility access_level) {
// Build the new module, then try to insert it. If it comes back as existing, then we discard. Else, it was inserted and we can process.
Module* new_module = nullptr;
ModuleContents m;
{
    if (module->dynamic) {
        auto dyn_mod = MakeUnique<DynamicModule>();
        dyn_mod->libname = module->libname->contents;
        new_module = dyn_mod.get();
        m.base = std::move(dyn_mod);     
    } else {
        auto mod = MakeUnique<Module>();
        new_module = mod.get();
        m.base = std::move(mod);
    }
    new_module->AST = module;
    m.access = access_level;
}
auto result = root.contents.insert(std::make_pair(module->name->name, std::move(m)));

这是根函数。 它从不同输入的多个线程并行调用,但具有相同的root

void Collater::Context::operator()(Wide::Parser::NamespaceAST* input, Module& root) {
std::for_each(input->contents.begin(), input->contents.end(), [&](Wide::Parser::AST* ptr) {
    if (auto mod_ptr = dynamic_cast<Wide::Parser::NamespaceAST*>(ptr)) {
        CollateModule(mod_ptr, root, Accessibility::Public);
    }
});
}

我不完全确定wtf会继续。 我只有一点共享状态,而且我只能原子地访问它,那为什么我的代码快死了?

编辑:这实际上完全是我自己的错。 崩溃发生在insert行中,我以为是问题所在,但不是 它根本与并发无关。 我测试的返回值, result 走错了路周围 -即truevalue existedfalsevalue did not exist ,而该标准定义了trueinsertion succeeded -即value did not exist 这不但严重破坏了内存管理,还导致了崩溃-尽管我不知道这到底是如何导致unordered_map代码崩溃的。 一旦插入正确的否定,它就可以正常工作。 这是因为我在跳过并发防护之前未正确测试单线程版本。

一种可能是您由于移动语义上的某些问题而崩溃。 崩溃是由空指针取消引用引起的吗? 如果您在移动对象后无意访问了该对象(例如ModuleContents ),则会发生这种情况。

崩溃也可能是并发错误导致的。 从插入和检索是原子的意义上来说, concurrent_unordered_map是线程安全的。 但是,存储在其中的任何内容均不会自动受到保护。 因此,如果多个线程检索相同的ModuleContents对象,则它们将共享Module内的AST树。 我不确定哪些引用是可修改的,因为我看不到任何const指针或引用。 任何共享和可修改的内容都必须受某种同步机制(例如锁)的保护。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM