C++11多线程编程报错?(提示nullptr)
1.在使用C++11编写多线程程序的时候,出现了一个报错
2.已经在自己加的各种技术群里问了,没人回
3.上过stackoverflow 只有一个类似的问题,但是无法解决
链接:https://stackoverflow.com/que...
4.报错的代码段:
这个很诡异,没有说明具体是哪里错了,报错定位在整个工程的最后一行"}"字符处
但是报错是在我修改了一部分逻辑代码之后出现的,之前没有错误,运行正常
这段代码如下:
代码
c++11标准
int jump_while = false;while (!jump_while) {
    newTree.begin_flag = true;
    //先写好一轮的代码,然后将其转化为循环,并思考终止条件 
    newTree.random_chooser();   //首先确定要随机选择的这一轮的传感器是哪些 
    cout << "Choosing phase successful" << endl;   //完成选择 
    time_consumption += double(1.0 / newTree.get_frenquency());  //该轮时间计数开始 
    std::future <Node*> *result = new std::future <Node*>[newTree.source_node_sent_in_a_round];  //创建获取进程返回结果的future对象 
    vector <thread*> thread_container;
    for (int i = 0; i < newTree.source_node_sent_in_a_round; i++) {
        int random_index = newTree.random_choosed[i];
        packaged_task<Node*(Node*)> *pac = new packaged_task<Node*(Node*)>(&Tree::transmit);
        thread *p = new thread(std::ref(*pac), newTree.vec[random_index]); //创建线程 , 防止被回收机制回收, 使用指针 
        thread_container.push_back(p);  //防止内存泄露,收集以备释放
        result[i] = (*pac).get_future();  //绑定future对象, 获取线程返回结果 
        (*p).join();  //所有线程阻塞主线程 
    }
    newTree.begin_flag = true;
    newTree.my_condition.notify_all(); //统一开始当前的这一局数据收集请求指令 
    for (int i = 0; i < newTree.source_node_sent_in_a_round; i++) {
        Node* re = result[i].get();  //每一个线程开始尝试捕捉结果,并阻塞 
        if (re != nullptr) {  //某一个线程获得返回值,在主线程开始判断 
                           //计算得到结果,此时其他线程应该停止模拟???怎么实现? 
            jump_while = true;
            die_first = re;
            break;
        }
    }
    for (int i = 0; i < newTree.source_node_sent_in_a_round; i++) {
        delete thread_container[i]; //释放内存
    }
}
补充一下引用的头文件和和结点类信息(stackoverflow上提供了)
#include <vector>#include <iostream>
#include <thread>
#include <mutex>
#include <queue>
#include <cmath>
#include <sstream>
#include <fstream>
#include <cstring>  //for memset
#include <algorithm>
#include <windows.h>
#include <future>
#include <condition_variable>
using namespace std;
class Node {
public:
    int num;
    double energy;
    double x, y;
    bool visited;
    Node* father;
    vector <Node*> child;
    int child_num;
    Node(int& node_num, double energy, double x, double y) {
        this->visited = false;
        this->num = node_num;
        this->energy = energy;
        this->x = x;
        this->y = y;
        this->father = NULL;
        this->child_num = 0;
        node_num++;
    }
    ~Node() {}
    Node* remove_child(Node*);
    void add_child(Node*);
};
Tree class信息:
class Tree {public:
    bool begin_flag;
    mutex begin_lock;
    vector <mutex*> my_lock;
    condition_variable my_condition;
    double THRESHOLD;
    int level_num;
    int SINK_ID; //from 0 to n - 1
    Node* root;
    double Eelec;
    double Efs;
    double Emp;
    double k;
    int frequency;
    double initial_energy_for_sink_node;
    double initial_energy_for_average_node;
    vector <Cordinate> c_vec;
    double communication_range;
    int source_node_sent_in_a_round;
    int number_of_each_node_package;
    int num_getter();
    double get_distance(Node* p1, Node* p2);
    bool able_conn(Node* p1, Node* p2, double communication_range);
    double send_energy(Node* p1, Node* p2);
    double receive_energy();
    int get_average_children_num(int l);
    bool verify_conn(Cordinate c1, Cordinate c2);
    Cordinate random_helper();
    Tree();
    ~Tree();
    vector <Node*> vec; //to storage node[i]'s info (vec[i] = node[i]) 
    vector <vector <Node*> > v2d; //to storage node[i]'s able connected node (v2d[i][j] = node v2d[i][j] able to communicate with node[i])
    vector <vector <Node*> > level; //to storage each level's node (level[i] represents for all nodes in the level[i])
    vector <int> node_in_tree_vec;
    vector <int> random_choosed;
    void random_data_generator();
    Node* buildTree();
    int get_level_num();
    int level_counter(Node* root);
    Node* get_sink();
    void levelizer(Node* root, int count);
    Node* transmit(Node* source);
    void random_chooser();
    int get_frenquency();
    void topDownBalancing();
    void downTopBalancing();
    void levelOrderTraverse();
    void show_residual_energy();
    int get_source_node_sent_in_a_round();
    string name_getter();
};
报错信息(编译环境visual studio 2015)

报错信息(编译环境DEV-C++)
另外也使用过GCC 4.8.1 release编译(DEV-C++ 5.7.1)
报错信息较多一些:
希望得到大神的指点,多谢!
回答:
看你的业务逻辑应该是从tree中随机选择N个节点,然后并行计算N个节点,获取到某个节点结果后就结束.
- transmit编译错误,参考- std::function调用成员函数- auto *pac = new packaged_task<Node*(Tree::*)(Node*)>(std::bind(&Tree::transmit, &newTree, std::placeholders::_1));
- packaged_task/- future/- thread不需要使用- new,- future装到里- std::vector就行,- thread可以直接- detach,- packaged_task直接- move到- thread里- std::vector<std::future<Node*>> futures;- for (int i = 0; i < newTree.source_node_sent_in_a_round; i++) { - int random_index = newTree.random_choosed[i]; - std::packaged_task<Node*(Tree::*)(Node*)> pac{std::bind(&Tree::transmit, &newTree, std::placeholders::_1)}; - futures.push_back(pac.get_future()); - std::thread(std::move(pac), newTree.vec[random_index]).detach(); - } - for (auto& future : futures) { - auto* node = future.get(); - } 
- 提前结束线程比好好的做法就是做atomic_bool在大量不可中断计算前做埋点检查,抛出异常用RAII机制释放资源,强制结束线程会有资源释放的问题.
- 直接使用std::async就行,不需要packaged_task和thread.
- 可以试试用libq
- 最好用std::unique_ptr或者std::shared_ptr,尽量少用裸指针
回答:
错误出在这里:
packaged_task<Node*(Node*)> *pac = new packaged_task<Node*(Node*)>(&Tree::transmit);Tree类的transmit方法虽然接收Node*返回Node*,但这是一个成员函数,所以实际类型并不是Node*(Node*),VS和GCC的报错信息其实也说明了这一点,传入的类型是Node*(Tree::*)(Node*)。
另外多嘴一句:
创建线程 , 防止被回收机制回收, 使用指针
这是什么鬼?C++哪来的回收机制……你只有new没有delete,怕是会面临内存泄漏。或许你还需要考虑一下对象的生命周期。
以上是 C++11多线程编程报错?(提示nullptr) 的全部内容, 来源链接: utcz.com/p/191552.html








