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