c++ - 为指针赋值时出现段错误 C++

标签 c++ pointers parallel-processing segmentation-fault

当我运行以下并行代码时,我在第 18 行(两次打印之间)的分配处遇到段错误。我不太明白到底是什么原因造成的。

这是一个描述问题的最小工作示例:

#include <iostream>
#include <numeric>
#include <vector>
#include <thread>


struct Worker{

    std::vector<int>* v;
    
    void f(){
            
        std::vector<int> a(20);
        std::iota(a.begin(), a.end(), 1);

        auto b = new std::vector<int>(a);
        std::cout << "Test 1" << std::endl;
        v = b;
        std::cout << "Test 2" << std::endl;
    }
};

int main(int argc, char** argv) {

    int nw = 1;
 
    std::vector<std::thread> threads(nw);
    std::vector<std::unique_ptr<Worker>> W;

    for(int i = 0; i < nw; i++){
        W.push_back(std::make_unique<Worker>());
        threads[i] = std::thread([&]() { W[i]->f(); } );

        // Pinning threads to cores
        cpu_set_t cpuset;
        CPU_ZERO(&cpuset);
        CPU_SET(i, &cpuset);
        pthread_setaffinity_np(threads[i].native_handle(), sizeof(cpu_set_t), &cpuset);
    }

    for (int i = 0; i < nw; i++) {
        threads[i].join();
        std::cout << (*(W[i]->v))[0] << std::endl;
    }
    
}

似乎用 -fsanitize=address 编译它,代码工作正常,但性能最差。我怎样才能让它发挥作用?

最佳答案

std::vector 不是线程安全的。 C++ 库中的容器都不是线程安全的。

threads[i] = std::thread([&]() { W[i]->f(); } );

新的执行线程通过引用捕获 vector 并访问它。

W.push_back(std::make_unique<Worker>());

原始执行线程不断修改此处的 vector ,而不与任何新执行线程同步对 W vector 的访问。任何 push_back 都可能使 vector 的现有内容无效,以便重新分配它,并且如果不同的执行线程尝试同时获取 W[i],而重新分配后,欢闹随之而来。

这是未定义的行为。

您必须使用互斥体同步对 vector 的访问,或者使用任意数量的已知技术确保 vector 永远不会被重新分配。提前足够大的 reserve() 应该可以解决问题。

此外,有人指出 i 也是通过引用捕获的,因此当每个新的执行线程启动时,它的值可以是任何值。

关于c++ - 为指针赋值时出现段错误 C++,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63013047/

相关文章:

c++ - 使用点和单元手动将网格插入 CGAL

c++ - 在模板中推断子类模板类型

c - 空指针问题

windows - 在 PowerShell 中写入具有多个作业的文件

C++ 算法循环 - 并行处理?

python - 在新进程中执行 python 代码比在主进程中慢得多

c++ - 在 C++ unordered_map 中调用一个不存在的键的方法

c++ - 需要帮助理解为什么在 OpenGL 中没有任何东西被绘制到屏幕上,过剩

使用 malloc 时出现编译器错误(需要左值作为赋值的左操作数)

c - C是否检查指针是否越界而不取消引用指针?