zoukankan      html  css  js  c++  java
  • std::queue

    std::queue 是 stl 里面的容器适配器, 用来适配FIFO的数据结构。

    std::queue, 入队列的方法是: std::queue::push(),

    出队列的方法是: std::queue::pop(), 为了异常安全, 这个方法返回void, 所以通常调用std::queue::front(), 查看队列头部的元素, 然后调用std::queue::pop(), 让元素出队列.

      今天在写一个服务器程序的时候,发现请求量大的时候,程序发生崩溃,原因是我传入某个函数的string的size()过大。
    这个程序是一个典型的生产者/消费者:生产者产生的信息放入 string,然后加锁放入std::queue中;消费者线程加锁,从std::queue.front()中获得对象的应用,然后pop()队头元素。一切看起来都是那么清晰简单。
    消费者的代码看起来就像是这样:

    为什么从队列取出string后,size就变了?
    试了很多种方法,最后只删除了一个符号,程序就正常了:

    通过上面的问题的解决,我了解了:原来queue的pop()方法会调用string的析构函数,引用指向一个已经析构的对象,当然会出错。
    真的是这样吗?我又做了如下的三个实验:
    //--------------------- test_queue_pop.cpp-----------------------------

    #include <stdio.h>
    #include <queue>
    #include <string>
    using namespace std;
    
    #include <pthread.h>
    #include <unistd.h>
    
    
    void test1()  //第一个实验,在一个线程里面,并没有问题
    {
    queue<string> q;
    string str1("str1");
    printf("str1=%08X, len=%u/n", (unsigned int)str1.data(), str1.size());
    q.push(str1);
    string& temp = q.front();
    printf("temp=%08X, len=%u/n", (unsigned int)temp.data(), temp.size());
    q.pop();
    printf("temp=%08X, len=%u/n", (unsigned int)temp.data(), temp.size());
    }
    
    void* _thread_func(void* param)
    {
    queue<string>& q = *(queue<string>*)param;
    string& temp = q.front();
    printf("temp=%08X, len=%u/n", (unsigned int)temp.data(), temp.size());
    q.pop();
    printf("temp=%08X, len=%u/n", (unsigned int)temp.data(), temp.size());
    return NULL;
    }
    
    void test2()    // 第二个实验:两个线程,还是没有问题
    {
    queue<string> q;
    string str1("str1");
    printf("str1=%08X, len=%u/n", (unsigned int)str1.data(), str1.size());
    q.push(str1);
    pthread_t thread;
    pthread_create(&thread, NULL, _thread_func, &q);
    pthread_join(thread, NULL);
    }
    
    void* _thread_func_1(void* param)
    {
    queue<string>& q = *(queue<string>*)param;
    string str1("str1");
    printf("str1=%08X, len=%u/n", (unsigned int)str1.data(), str1.size());
    q.push(str1);
    return NULL;
    }
    
    void* _thread_func_2(void* param)
    {
    queue<string>& q = *(queue<string>*)param;
    sleep(1);
    string& temp = q.front();
    printf("temp=%08X, len=%u/n", (unsigned int)temp.data(), temp.size());
    q.pop();
    printf("temp=%08X, len=%u/n", (unsigned int)temp.data(), temp.size());
    return NULL;
    }
    
    void test3()    //第三个实验:我在项目中出现的错误终于重现了
    {
    queue<string> q;
    pthread_t thread1, thread2;
    pthread_create(&thread1, NULL, _thread_func_1, &q);
    pthread_create(&thread2, NULL, _thread_func_2, &q);
    pthread_join(thread1, NULL);
    pthread_join(thread2, NULL);
    }
    
    int main()
    {
    test1();
    printf("====================================/n");
    test2();
    printf("====================================/n");
    test3();
    return 1;
    }
    

      

    为什么呢?为什么pop()仅仅只在多线程环境下才调用对象的析构函数?这只能理解为stl的bug了。
    还好,总是使用operator=就好!

  • 相关阅读:
    springboot将接口内容快速生成接口文档导出,swagger将api文档以表格文档导出
    IDEA2019.2或2019.3激活码失效后重新激活教程
    Java代码自动生成,生成前端vue+后端controller、service、dao代码,根据表名自动生成增删改查功能
    百度网盘下载慢解决办法,最新.浏览器下载速度突破方法
    smartGit 版本19.1没有settings文件如何破解
    arp欺骗软件(来自互联网)
    关闭学生端v1.0(附链接)
    [TODO]multiaet/set/multimap/map
    树状数组【洛谷3374】
    luoguP1439
  • 原文地址:https://www.cnblogs.com/honker/p/3774417.html
Copyright © 2011-2022 走看看