Повреждение памяти с concurrent_queue - PullRequest
1 голос
/ 24 декабря 2011

У меня проблема с повреждением памяти в моей параллельной системе.

У меня есть распределитель памяти, который не является потокобезопасным, и я пытаюсь сделать его потокобезопасным, обслуживая несколько экземпляров для различных потоков по требованию. Этот код показывает систему, которую я использую. Это эффективно создает очередь экземпляров. Если очередь пуста, создается новый экземпляр, иначе он удаляется из очереди. Когда поток завершается с экземпляром, он помещает его обратно в очередь для последующего использования позже.

Concurrency::concurrent_queue<std::shared_ptr<Memory::Arena>> result_memory_arenas;
//std::
struct ConcurrentMemoryArena {
    Context* ptr;
    std::shared_ptr<Memory::Arena> arena;
    Memory::Arena& operator*() { return *arena; }
    Memory::Arena* operator->() { return arena.get(); }
    ~ConcurrentMemoryArena() {
        if (arena)
            ptr->result_memory_arenas.push(arena);
    }
    ConcurrentMemoryArena(Context* owner)
        : ptr(owner) {}
    ConcurrentMemoryArena(ConcurrentMemoryArena&& other) {
        arena = std::move(other.arena);
        other.arena = nullptr;
        ptr = other.ptr;
    }
};
ConcurrentMemoryArena ConcurrentGetResultArena() {
    ConcurrentMemoryArena ret(this);
    /*if (!result_memory_arenas.empty()) {
        ret.arena = result_memory_arenas.front();
        result_memory_arenas.pop();
        return ret;
    }*/
    if (result_memory_arenas.try_pop(ret.arena)) {
        return ret;
    }
    ret.arena = std::make_shared<Memory::Arena>();
    return std::move(ret);
}

Мой код довольно мал.

Concurrency::concurrent_vector<Wide::Parser::NamespaceAST*> ASTs;
Concurrency::parallel_for_each(filenames.begin(), filenames.end(), [&](String* ptr) {
    auto arena = ConcurrentGetResultArena();
    ASTs.push_back(parser(lexer(ptr, *arena), *arena));
});

И lexer, и parser являются "чистыми" функциями и никоим образом не являются параллельными или совместно используемыми.

Система работает нормально, но когда эта функция завершена, память обнуляется, и под этим я подразумеваю весь объект, содержащий result_memory_arenas, а когда очередь разрушается, она пытается уничтожить shared_ptr s, которые имеют неверные указатели, вызывающие сбой. Но я не вижу, откуда проблема. Я использовал предварительно предоставленные параллельные контейнеры, shared_ptr является потокобезопасным, а функции, которые фактически вызываются параллельно, являются чистыми.

Редактировать: Другие объекты были мертвы, потому что, как ни странно, очередь на самом деле уничтожается последней. Я прервал добавление в очередь, и все они действительны shared_ptr. Когда функция завершена, все они действительны shared_ptr с . Так почему же при уничтожении очереди она уничтожает бюст shared_ptr?

Снова отредактируйте: я обнаружил ошибку в неинициализированной памяти в реализации, которая меня не удивляет. Удивительно, что этот материал прошел любые тесты с классами, отличными от POD.

1 Ответ

0 голосов
/ 26 декабря 2011

Отследил это до ошибки реализации, опять же. Microsoft должна нанять меня в качестве тестера.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...