c++ - 任务在删除其中一个迭代对象时会导致段错误

标签 c++ iterator openmp

由于 OpenMP 任务之一删除了 it 指向的元素之一,下一个代码崩溃了。我该如何解决这个问题?代码必须使用 OpenMP 任务来实现。

#pragma omp parallel
{
   #pragma omp single nowait
   {
      for (std::list<Class*>::iterator it = myClass.begin(); it != myClass.end();) {
         if ((*it)->getNumber() == 0) {
            #pragma omp critical
            it = myClass.erase(it);
         }
         else {
            #pragma omp task firstprivate(it)
            { 
               bool result = (*it)->function(t);
               if ( result ) {
                  #pragma omp critical
                  it = myClass.erase(it);
               }
            }
         }
         ++it;
      }
   }
   #pragma omp taskwait
}

最佳答案

std::list 中删除节点使用多线程非常棘手。您不仅要删除临界区中的节点,还要注意用于列表遍历的迭代器。

当您使用一个线程执行 ++it 时和其他线程做 list.erase(it) ,你可能会发现 it 指向的节点在 ++it 之前可能已经被删除了完成了,正在做++在指向不存在节点的迭代器上将导致未定义的行为。

一个可能的解决方案是确保 ++it在删除/更改节点之前完成,如@sehe 所示,您不应该 ++iterase之后.

#pragma omp parallel
{
   #pragma omp single nowait
   {
      for (std::list<Class*>::iterator it = myClass.begin(); it != myClass.end();) {
         if ((*it)->getNumber() == 0) {
            #pragma omp critical
            it = myClass.erase(it);
         }
         else {
            std::list<Class*>::iterator local_it=it++;
            #pragma omp task firstprivate(local_it)
            { 
               bool result = (*local_it)->function(t);
               if ( result ) {
                  #pragma omp critical
                  myClass.erase(local_it);
               }
            }
         }
      }
   }
   #pragma omp taskwait
}

关于c++ - 任务在删除其中一个迭代对象时会导致段错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19691720/

相关文章:

c++ - C++ 中的临界区和返回值

python - 在所有其他部分完全运行后是否可以运行变形器部分?

iterator - 如何遍历向后范围?

C++智能指针

c# - c# 容器中的 push_back 操作

iterator - 在 Rust 中迭代切片的值而不是引用?

c++ - 任务 : OpenMP directive name required

c++ - 当使用不同的索引变量索引数组时,OpenMP for 循环?

c - 将 pragma omp parallel for 与 SSE 代码 : How to reset FPU? 混合

c++ - 如何在c++0x线程中使用wait_for