【问题标题】:What to do if the object is destroyed during the call in C++如果在 C++ 中调用过程中对象被破坏怎么办
【发布时间】:2021-02-09 10:34:48
【问题描述】:

这是我的测试代码

class bar
{
public:
    explicit bar(int x) : num(x) {}
    int get_num()
    {
        return num;
    }

private:
    int num;
};

shared_ptr<bar> ptr_store;

void get_func()
{
    while (1)
        printf("get_num:%d\n", ptr_store->get_num());
};

void set_func()
{
    while (1)
        //ptr_store = make_shared<bar>(1);
        atomic_exchange(&ptr_store, make_shared<bar>(1));

}

int main()
{
    ptr_store = make_shared<bar>(-1);
    std::thread t1(get_func);
    std::thread t2(set_func);
    t1.join();
    t2.join();
}

我想知道为什么这个程序不会进行核心转储?

如果t1t1 使用ptr_store-&gt;get_num()t2 中的set_func 破坏了原点ptr_store,可能会导致一些故障? 由shared_ptr 保证吗?或者只是巧合。

Test environment:
OS: Ubuntu 20.04 LTS
Clang: clang version 3.9.1
G++: gcc version 7.5.0 

更新: 我认为两个线程不可能访问一个对象。 atomic_exchangereset 可以被认为是原子操作。 设置新对象时,不会更改旧对象。

【问题讨论】:

    标签: c++ multithreading c++11 shared-ptr stdatomic


    【解决方案1】:

    我想知道为什么这个程序不会进行核心转储?

    C++ 标准中没有“核心转储”之类的东西。这些词不在词汇表中。有“未定义的行为”,你的程序有它。有一个data race

    如果多个执行线程在没有同步的情况下访问同一个 std::shared_ptr 对象,并且这些访问中的任何一个使用 shared_ptr 的非常量成员函数,则将发生数据竞争,除非所有此类访问都通过这些函数执行 source .

    atomic_exchange 可以,但你 need atomic_load 在另一个线程中。

    请注意,所有这些在 C++20 中都已弃用。请改用std::atomic&lt;std::shared_ptr&lt;bar&gt;&gt;

    【讨论】:

    • 但是,请注意,此版本的 atomic_load 在 C++20 中已弃用!您应该将全局指针设为 std::atomic&lt;std::shared_ptr&lt;bar&gt;&gt;
    • @SebastianRedl 是的,atomic_exchange 也已弃用,添加了注释。
    • ... 而 UB 确实 not 的意思是“需要崩溃”。从字面上看,它意味着任何事情都可能发生,您必须查看由一个特定实现为一个特定 CPU 生成的 asm 以确定是什么。其他效果很常见,例如释放后的内存只在空闲列表上而不是未映射时使用。
    【解决方案2】:

    现在我通过@n 修复我的代码。 '代词' m. 的回答。 现在看来工作得很好

    #include <bits/stdc++.h>
    #include <iostream>
    #include <utility>
    #include <thread>
    #include <chrono>
    #include <functional>
    #include <atomic>
    #include <unistd.h>
    #include <bits/shared_ptr_atomic.h>
    
    using namespace std;
    
    class bar
    {
    public:
        explicit bar(vector<int> &in) : num(-1)
        {
            for (auto iter : in)
                v.push_back(iter);
        }
        int get_num()
        {
            for (auto iter : v)
            {
                num = max(iter, num);
            }
            if (num >= 100)
            {
                printf("Fault %d\n", num);
            }
            return num;
        }
    
    private:
        int num;
        vector<int> v;
    };
    
    shared_ptr<bar> ptr_store;
    
    int st;
    
    void get_func()
    {
        for (int k = 0; k <= 10000; k++)
        {
            auto temp = atomic_load_explicit(&ptr_store, std::memory_order_seq_cst);
            printf("Get_num %d\n", temp->get_num());
        }
    }
    
    void set_func()
    {
        for (int k = 0; k <= 10000; k++)
        {
            vector<int> v;
            int sz = rand() % 100;
            for (int i = 0; i < sz; i++)
                v.push_back(rand() % 100);
            atomic_exchange(&ptr_store, make_shared<bar>(v));
        }
    }
    
    int main()
    {
        srand((unsigned)time(NULL));
        vector<int> v = {1, 2, 3};
        ptr_store = make_shared<bar>(v);
        std::thread t1(get_func);
        std::thread t2(set_func);
        t1.join();
        t2.join();
    }
    
    // g++ atomic_exchange.cpp -o atomic_exchange -pthread && ./atomic_exchange > atomic_exchange.out
    

    【讨论】:

      猜你喜欢
      • 2017-10-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-12-25
      • 2017-05-26
      • 2014-05-26
      • 1970-01-01
      • 2015-02-14
      相关资源
      最近更新 更多