簡體   English   中英

構造函數中的 pthread_create 段錯誤

[英]pthread_create in constructor segfault

我發現,在下面的這個小例子中,如果我在我的結構的構造函數中調用 pthread_create,我會在調用 pthread_mutex_lock() 時隨機得到一個段錯誤。

有時,第一位哲學家的姓名字段為空。

如果我在構造函數之后將 pthread_create 移動到 run() function,則沒有段錯誤。

似乎對 pthread_create 的調用發生在所有成員初始化之前。 class 的成員初始化列表不應該在調用構造函數體之前完成嗎?

感謝您的任何提示!

clang 版本 9.0.0 (tags/RELEASE_900/final) 目標:x86_64-apple-darwin17.7.0

真誠的,喬治

#include <array>
#include <iostream>
#include <pthread.h>
#include <string>
#include <vector>

using namespace std;


struct chopstick
{
        pthread_mutex_t mutex;
        chopstick()
        {
                pthread_mutex_init(&mutex,nullptr);
        }
        ~chopstick()
        {
                pthread_mutex_destroy(&mutex);
        }

};

void* feed(void* data);
struct philosopher
{
        pthread_t thread;
        string name;
        unsigned mouthfuls;
        chrono::seconds sec;
        chopstick &left, &right;

        pthread_t& get_thread() { return thread; }

        philosopher(const string &s, chopstick &l, chopstick &r): name(move(s)), left(l), right(r), mouthfuls(0)
        /*
                enable below to avoid segfault
        {}
        void run()  
        */
        {
                pthread_create(&thread, nullptr, feed, this);
        };

};

void* feed(void* data)
{
        philosopher & a = *static_cast<philosopher*>(data);
        while (a.mouthfuls < 20)
        {
                pthread_mutex_lock(&a.left.mutex);
                pthread_mutex_lock(&a.right.mutex);
                cout << "Apostle " << a.name << " thread id " << pthread_self() 
                        << " acquired a chopstick at count: " << a.mouthfuls << endl;
                ++a.mouthfuls;
                pthread_mutex_unlock(&a.right.mutex);
                pthread_mutex_unlock(&a.left.mutex);
        }
        return nullptr;
}

int main (int argc, char const * argv[])
{
        array<string, 12> names {"John", "Thaddeus", "Simon Peter", "James", "Judhas", "Bartholomew", "Matthew", "Philip", "Simon Zealot", "Thomas", "Andrew", "James the Lesser" };
        array<chopstick,names.size()> sticks;
        vector<philosopher> philosophers;

        for (int i=0; i+1<names.size(); ++i)
                philosophers.emplace_back( names[i],sticks[i],sticks[i+1] );
        philosophers.emplace_back(names[names.size()-1], sticks[0],sticks[names.size()-1]);
        //for (philosopher&  a: philosophers) a.run();  //<-- enable to avoid segfault
        for (philosopher&  a: philosophers) pthread_join(a.get_thread(), nullptr);

        return 0;

}

std::vector在代碼執行philosophers.emplace_back()時調整大小,這可以移動 memory 中的元素,從而使它們以前的地址變得無效,並且feed() function 最終使用其舊的無效地址訪問對象。

解決方法是使philosopher class 不可復制和不可移動,然后使用std::list<philosopher>std::forward_list<philosopher>代替std::vector<philosopher> std::liststd::forward_list不會移動 memory 中的元素,因此能夠存儲不可復制和不可移動的對象。

您可能還想使用std::thread代替pthread_tstd::mutex代替pthread_mutex_t std類是不可復制/可移動的,這將防止您在編譯時出現此錯誤。 此外,代碼不會檢查 pthread 函數的返回值是否有錯誤,而std::threadstd::mutex會為您執行此操作。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM