【问题标题】:Getting wrong output from boost lock free spsc queue从 boost lock free spsc 队列中得到错误的输出
【发布时间】:2015-10-22 06:58:29
【问题描述】:

我正在尝试使用 boost 库来实现用户定义数据类型的无锁队列,但我得到了错误的结果。

请帮我找出我做错的地方。

#include <boost/lockfree/spsc_queue.hpp>
#include <thread>
#include <iostream>
#include <string.h>
#include <time.h>   


class Queue
{
 private:
       unsigned char *m_data;
       int m_len;

 public:
       Queue(unsigned char *data,int len);

       Queue(const Queue &obj);

       ~Queue();  

       Queue & operator =(const Queue &obj);


       unsigned char *getdata()
       {
         return m_data;
       }

       int getint()
       {
           return m_len;
       }
};

Queue::Queue(unsigned char* data, int len)
{
      m_len=len;

      m_data=new unsigned char[m_len];

      memcpy(m_data,data,m_len);
}

Queue::Queue(const Queue& obj)
{
      m_len=  obj.m_len;

      m_data=new unsigned char[m_len];

      memcpy(m_data,(unsigned char *)obj.m_data,m_len);
}

Queue::~Queue()
{
   delete[] m_data;
   m_len=0;
}

Queue & Queue::operator =(const Queue &obj)
{
   if(this != &obj)
   {
      m_len=obj.m_len;

      m_data=new unsigned char[m_len];

      memcpy(m_data,(unsigned char *)obj.m_data,m_len);
   }

   return *this;
}

boost::lockfree::spsc_queue<Queue*> q(10);



void produce()
{
    int i=0;
    unsigned char* data=(unsigned char *)malloc(10);
    memset(data,1,9);

    Queue obj(data,10);

    Queue *pqueue=&obj;

    printf("%d\n",pqueue->getint());


    q.push(pqueue);

}

void consume()
{

    Queue *obj;

    q.pop(&obj);

    printf("%d\n",obj->getint());

}


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


//  std::thread t1{produce};
//  std::thread t2{consume};
//  
//  t1.join();
//  t2.join();
    produce();
    consume();

    return 0;
}

根据我在课堂上创建的 boost::lockfree::queue 要求。

  • 复制构造函数
  • 赋值运算符
  • 析构函数

如果有其他需要,请告诉我。 谢谢。

【问题讨论】:

标签: c++11 boost queue lock-free


【解决方案1】:
  1. 您在 C++ 中使用 malloc

    你死了。

    你还剩 2 条命。

    说真的,不要那样做。尤其是因为与delete[] 一起使用是明确的Undefined Behaviour


  2. 很遗憾你在这里失去了另一条生命:

    Queue obj(data,10);
    
    Queue *pqueue=&obj;
    q.push(pqueue);
    

    您存储指向本地的指针。更多Undefined Behaviour

    你还剩 1 条生命。


  3. 前世

    q.pop(&obj);
    

    您使用 迭代器 弹出。它将被视为输出迭代器。 您会得到一个返回值,指示弹出的元素数量和项目 将写入&amp;obj[0]&amp;obj[1]&amp;obj[2]等。

    你猜怎么着? Undefined Behaviour.

    另见:Boost spsc queue segfault

    你死了。


  4. 你已经死了。但是你放弃了你的来世与

    printf("%d\n",obj->getint());
    

    由于pop 可能没有弹出任何内容(队列可能为空),这本身就是Undefined Behaviour


有趣的是,你谈到了所有这些构造函数要求但是你将指针存储在无锁队列中......?!直接写吧:

typedef std::vector<unsigned char> Data;

class Queue {
    private:
    Data m_data;

    public:
    Queue(Data data) : m_data(std::move(data)) {}
    Queue() : m_data() {}
    unsigned char const *getdata() const { return m_data.data(); } 
    size_t               getint()  const { return m_data.size(); } 
};

boost::lockfree::spsc_queue<Queue> q(10);

Live On Coliru

注意事项:

  • 需要让消费者检查pop的返回码。推送可能没有发生,并且无锁队列不会阻塞。

  • 你不需要那个装置。一路传递向量即可:

C++ 代码

Live On Coliru

#include <boost/lockfree/spsc_queue.hpp>
#include <thread>
#include <iostream>
#include <vector>

typedef std::vector<unsigned char> Queue;

boost::lockfree::spsc_queue<Queue> q(10);

void produce() {
    Queue obj(10, 1);

    std::cout << __FUNCTION__ << " - " << obj.size() << "\n";

    q.push(std::move(obj));
}

void consume() {
    Queue obj;
    while (!q.pop(obj)) { }

    std::cout << __FUNCTION__ << " - " << obj.size() << "\n";
}

int main() {
    std::thread t1 {produce};
    std::thread t2 {consume};

    t1.join();
    t2.join();
}

【讨论】:

  • 我已经把 UB 的列表做得更完整了。对不起,这听起来有点像抨击。但是如果您不安全,真的不要使用 C++。世界本来就是一个危险的地方。
猜你喜欢
  • 2020-08-13
  • 2019-04-08
  • 2018-02-07
  • 1970-01-01
  • 1970-01-01
  • 2015-02-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多