由于 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 所示,您不应该 ++it
在erase
之后.
#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/