尝试实现多线程队列时_M_构造null无效错误

ani*_*udh 0 c++ multithreading

我正在尝试使用简单的线性方法来实现优先级队列,如多处理器编程艺术中所述。我是 C++ 新手,很难排除故障。

我已经实现了两个模板类,并使用简单的测试方法来测试它们。由于我无法找出错误,因此我粘贴了以下所有三个类以供参考。

我知道_M_ construct null not valid在尝试使用 构造字符串时会出现这种情况nullptr,但不确定我在哪里这样做。

创建的三个类如下:

bin.h

#include <mutex>
#include <deque>
#include <memory>
#include <iostream>
using namespace std;

namespace priority
{
    template<typename T>
    class Bin
    {
    private:
        std::deque<T> v;
        std::mutex m;
    public:
        Bin() {
        }

        Bin(const Bin &o) {
            
        }

        const Bin &operator=(const Bin &other) {
            return *this;
        }

        void put(T item) {
            std::lock_guard<std::mutex> lock(m);
            v.push_back(item);
        }

        T *get() {
            std::lock_guard<std::mutex> lock(m);
            if (v.size() == 0) {
                return nullptr;
            }
            else {
                T val = v.front();
                T *ptr_val = &(val);
                v.pop_front();
                return ptr_val;
            }
        }

        bool isEmpty() {
            std::lock_guard<std::mutex> lock(m);
            return v.size() == 0;
        }
        
    };  
}
Run Code Online (Sandbox Code Playgroud)

简单线性.h

#include <mutex>
#include <vector>
#include <memory>
#include "Bin.h"

namespace priority
{   
    template<typename T>
    class SimpleLinear
    {
    private:
        int range;
        std::vector<Bin<T>> pqueue;
    public:
        SimpleLinear(int range){
            this->range = range;

            for (int i = 0; i < range; i++)
            {
                pqueue.push_back(Bin<T>());
            }

        }

        void add(T item, int key) {
            pqueue[key].put(item);
        }

        T removeMin() {
            for (int i = 0; i < range; i++)
            {
                T *item = pqueue[i].get();
                if (item != nullptr) {
                    return *item;
                }
            }
            return nullptr;
        }
        
    };
}
Run Code Online (Sandbox Code Playgroud)

测试.cpp

#include <iostream>
#include <vector>
#include <thread>
#include <algorithm>
#include "SimpleLinear.h"
using namespace std;
using namespace priority;

void te(SimpleLinear<string> s, int thread_id) {

    s.add("sundar"+to_string(thread_id), thread_id);
    s.add("akshaya"+to_string(thread_id), 3);
    s.add("anirudh"+to_string(thread_id), 1);
    s.add("aaditya"+to_string(thread_id), 5);
    cout << s.removeMin() << endl;
    cout << s.removeMin() << endl;
    cout << s.removeMin() << endl;

}


int main(int argc, char const *argv[])
{   

    SimpleLinear<string> s(100);
    std::vector<std::thread> v;

    for (int i = 0; i < 100; i++)
    {   
        // if (i % 2 == 0)
            v.push_back(thread(te, std::ref(s), i));
        // else
            // v.push_back(thread(t, std::ref(s), i));

        
    }
    for_each(v.begin(), v.end(), std::mem_fn(&std::thread::join));
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

我收到错误:

terminate called after throwing an instance of 'std::logic_error'
  what():  basic_string::_M_construct null not valid
terminate called recursively
terminate called recursively
terminate called recursively
Aborted (core dumped)
Run Code Online (Sandbox Code Playgroud)

Max*_*kin 5

它崩溃的原因之一是,SimpleLinear<T>::removeMin当Tis 时std::string,return nullptr从 构造一个字符串nullptr。basic_string::_M_construct null not valid基本上说它std::string(nullptr)被调用了。


它可能崩溃的另一个原因是get函数返回指向局部变量的指针。当函数返回时,局部变量被销毁。这会导致未定义的行为。

修复:

bool get(T& result) {
    std::lock_guard<std::mutex> lock(m);
    if (v.empty()) 
        return false;
    result = v.front();
    v.pop_front();
    return true;
}
Run Code Online (Sandbox Code Playgroud)

并像这样调用它:

T removeMin() {
    T result;
    for(int i = 0; i < range; i++)
        if(pqueue[i].get(result))    
            break;
    return result;
}
Run Code Online (Sandbox Code Playgroud)