我的并发系统中存在内存损坏问题。
我有一个不是线程安全的内存分配器,我试图通过按需向多个线程提供多个实例来使其成为线程安全的。此代码显示我正在使用的系统。它有效地构建了一个实例队列。如果队列为空,则创建一个新实例,否则将从队列中取出一个实例。当线程完成实例时,它会将其推回到队列中以便以后再次使用。
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
,当队列破坏时,它会试图破坏{{1}有无效指针的s,导致崩溃。但我无法看到问题的来源。我使用了预先提供的并发容器,shared_ptr
是线程安全的,并且实际上并行调用的函数是纯粹的。
编辑:其他对象已经死了,因为有趣的是,队列实际上是最后被摧毁的东西。我没有加入队列,而且它们都是有效的shared_ptr
。功能完成后,它们全部有效shared_ptr
s 。那么为什么在摧毁队列时,它会破坏一个半身像shared_ptr
?
再次编辑:我在实现中将其追溯到未初始化的内存错误,这并不会让我感到惊讶。令人惊讶的是,这些东西通过了非POD类的任何测试。
答案 0 :(得分:0)
再次将此问题追溯到实施错误。微软应该雇用我作为测试人员。