Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/163.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ boost::线程池中的函数解除分配分段错误_C++_Boost Thread_Boost Bind_Boost Function - Fatal编程技术网

C++ boost::线程池中的函数解除分配分段错误

C++ boost::线程池中的函数解除分配分段错误,c++,boost-thread,boost-bind,boost-function,C++,Boost Thread,Boost Bind,Boost Function,我试图创建一个线程池,在所有子线程完成之前阻止主线程。这方面的实际用例是一个“控制器”流程,它生成独立的流程供用户交互 不幸的是,当main退出时,会遇到分段错误。我无法找出这个分段错误的原因 我编写了一个Process类,它只不过是打开一个shell脚本(称为waterer.sh,其中包含sleep5)并等待pid退出。初始化进程类,然后将Wait()方法放置在线程池中的一个线程中 调用~thread\u pool()时会出现问题。std::queue无法正确解除分配传递给它的boost::f

我试图创建一个线程池,在所有子线程完成之前阻止主线程。这方面的实际用例是一个“控制器”流程,它生成独立的流程供用户交互

不幸的是,当
main
退出时,会遇到分段错误。我无法找出这个分段错误的原因

我编写了一个
Process
类,它只不过是打开一个shell脚本(称为
waterer.sh
,其中包含
sleep5
)并等待
pid
退出。初始化
进程
类,然后将
Wait()
方法放置在线程池中的一个线程中

调用
~thread\u pool()
时会出现问题。
std::queue
无法正确解除分配传递给它的
boost::function
,即使对
进程的引用仍然有效

#include <sys/types.h>
#include <sys/wait.h>
#include <spawn.h>

#include <queue>
#include <boost/bind.hpp>
#include <boost/thread.hpp>

extern char **environ;

class Process {
private:
    pid_t pid;
    int status;
public:

    Process() : status(0), pid(-1) {
    }

    ~Process() {
        std::cout << "calling ~Process" << std::endl;
    }

    void Spawn(char **argv) {
        // want spawn posix and wait for th epid to return
        status = posix_spawn(&pid, "waiter.sh", NULL, NULL, argv, environ);
        if (status != 0) {
            perror("unable to spawn");
            return;
        }
    }

    void Wait() {
        std::cout << "spawned proc with " << pid << std::endl;
        waitpid(pid, &status, 0);
        //        wait(&pid);
        std::cout << "wait complete" << std::endl;
    }

};
主要内容如下:

int main() {

    // input arguments are not required
    char *argv[] = {NULL};
    Process process;
    process.Spawn(argv);

    thread_pool pool(5);

    pool.run_task(boost::bind(&Process::Wait, &process));

    return 0;
}
此操作的输出为

creating 5 threads
~thread_pool
I am waiting... (from waiting.sh)
running task
spawned proc with 2573
running task
running task
running task
running task
wait complete
Segmentation fault (core dumped)
这是堆栈跟踪:

Starting program: /home/jandreau/NetBeansProjects/Controller/dist/Debug/GNU-    Linux/controller 
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
creating 5 threads
[New Thread 0x7ffff691d700 (LWP 2600)]
[New Thread 0x7ffff611c700 (LWP 2601)]
[New Thread 0x7ffff591b700 (LWP 2602)]
[New Thread 0x7ffff511a700 (LWP 2603)]
[New Thread 0x7ffff4919700 (LWP 2604)]
~thread_pool
running task
running task
spawned proc with 2599
[Thread 0x7ffff611c700 (LWP 2601) exited]
running task
[Thread 0x7ffff591b700 (LWP 2602) exited]
running task
[Thread 0x7ffff511a700 (LWP 2603) exited]
running task
[Thread 0x7ffff4919700 (LWP 2604) exited]
I am waiting...
wait complete
[Thread 0x7ffff691d700 (LWP 2600) exited]

Thread 1 "controller" received signal SIGSEGV, Segmentation fault.
0x000000000040f482 in boost::detail::function::basic_vtable0<void>::clear (
this=0xa393935322068, functor=...)
at /usr/include/boost/function/function_template.hpp:509
509           if (base.manager)
(gdb) where
#0  0x000000000040f482 in boost::detail::function::basic_vtable0<void>::clear (
this=0xa393935322068, functor=...)
at /usr/include/boost/function/function_template.hpp:509
#1  0x000000000040e263 in boost::function0<void>::clear (this=0x62ef50)
at /usr/include/boost/function/function_template.hpp:883
#2  0x000000000040cf20 in boost::function0<void>::~function0 (this=0x62ef50, 
__in_chrg=<optimized out>)
at /usr/include/boost/function/function_template.hpp:765
#3  0x000000000040b28e in boost::function<void ()>::~function() (
this=0x62ef50, __in_chrg=<optimized out>)
at /usr/include/boost/function/function_template.hpp:1056
#4  0x000000000041193a in std::_Destroy<boost::function<void ()> >(boost::function<void ()>*) (__pointer=0x62ef50)
at /usr/include/c++/5/bits/stl_construct.h:93
#5  0x00000000004112df in  std::_Destroy_aux<false>::__destroy<boost::function<void ()>*>(boost::function<void ()>*, boost::function<void ()>*) (
__first=0x62ef50, __last=0x62ed50)
at /usr/include/c++/5/bits/stl_construct.h:103
#6  0x0000000000410d16 in std::_Destroy<boost::function<void ()>*>(boost::function<void ()>*, boost::function<void ()>*) (__first=0x62edd0, __last=0x62ed50)
at /usr/include/c++/5/bits/stl_construct.h:126
#7  0x0000000000410608 in std::_Destroy<boost::function<void ()>*, boost::function<void ()> >(boost::function<void ()>*, boost::function<void ()>*, std::allocat---Type <return> to continue, or q <return> to quit---
or<boost::function<void ()> >&) (__first=0x62edd0, __last=0x62ed50)
at /usr/include/c++/5/bits/stl_construct.h:151
#8  0x000000000040fac5 in std::deque<boost::function<void ()>, std::allocator<boost::function<void ()> > >::_M_destroy_data_aux(std::_Deque_iterator<boost::function<void ()>, boost::function<void ()>&, boost::function<void ()>*>, std::_Deque_iterator<boost::function<void ()>, boost::function<void ()>&, boost::function<void ()>*>) (this=0x7fffffffdaf0, __first=..., __last=...)
at /usr/include/c++/5/bits/deque.tcc:845
#9  0x000000000040e6e4 in std::deque<boost::function<void ()>,  std::allocator<boost::function<void ()> > >::_M_destroy_data(std::_Deque_iterator<boost::function<void ()>, boost::function<void ()>&, boost::function<void ()>*>, std::_Deque_iterator<boost::function<void ()>, boost::function<void ()>&, boost::function<void ()>*>, std::allocator<boost::function<void ()> > const&) (
this=0x7fffffffdaf0, __first=..., __last=...)
at /usr/include/c++/5/bits/stl_deque.h:2037
#10 0x000000000040d0c8 in std::deque<boost::function<void ()>, std::allocator<boost::function<void ()> > >::~deque() (this=0x7fffffffdaf0, 
__in_chrg=<optimized out>) at /usr/include/c++/5/bits/stl_deque.h:1039
#11 0x000000000040b3ce in std::queue<boost::function<void ()>, std::deque<boost::function<void ()>, std::allocator<boost::function<void ()> > > >::~queue() (
this=0x7fffffffdaf0, __in_chrg=<optimized out>)
at /usr/include/c++/5/bits/stl_queue.h:96
#12 0x000000000040b6c0 in thread_pool::~thread_pool (this=0x7fffffffdaf0, 
---Type <return> to continue, or q <return> to quit---
__in_chrg=<optimized out>) at main.cpp:63  
#13 0x0000000000408b60 in main () at main.cpp:140
启动程序:/home/jandreau/NetBeansProjects/Controller/dist/Debug/GNU-Linux/Controller
[已启用使用libthread_db的线程调试]
使用主机libthread_db library“/lib/x86_64-linux-gnu/libthread_db.so.1”。
创建5个线程
[新螺纹0x7ffff691d700(LWP 2600)]
[新螺纹0x7ffff611c700(LWP 2601)]
[新螺纹0x7ffff591b700(LWP 2602)]
[新螺纹0x7ffff511a700(LWP 2603)]
[新螺纹0x7ffff4919700(LWP 2604)]
~thread_池
运行任务
运行任务
产生了2599的proc
[线程0x7ffff611c700(LWP 2601)已退出]
运行任务
[线程0x7ffff591b700(LWP 2602)已退出]
运行任务
[线程0x7ffff511a700(LWP 2603)已退出]
运行任务
[线程0x7ffff4919700(LWP 2604)已退出]
我在等待。。。
等待完成
[线程0x7ffff691d700(LWP 2600)已退出]
线程1“控制器”收到信号SIGSEGV,分段故障。
boost中的0x000000000040f482::detail::function::basic_vtable0::clear(
this=0xA3935322068,函子=…)
at/usr/include/boost/function/function_template.hpp:509
509 if(基本管理器)
(gdb)在哪里
#boost中的0 0x000000000040f482::详细信息::函数::基本表格0::清除(
this=0xA3935322068,函子=…)
at/usr/include/boost/function/function_template.hpp:509
#boost::function0::clear中的1 0x000000000040e263(此=0x62ef50)
at/usr/include/boost/function/function_template.hpp:883
#boost::function0::~function0中的2 0x000000000040cf20(此=0x62ef50,
__in_chrg=)
at/usr/include/boost/function/function_template.hpp:765
#boost::function::~function()中的3 0x000000000040b28e(
这=0x62ef50,uuu in_uchrg=)
at/usr/include/boost/function/function_template.hpp:1056
#标准中的4 0x000000000041193a:_销毁(boost::function*)(uu指针=0x62ef50)
at/usr/include/c++/5/bits/stl_construct.h:93
#std:_Destroy_aux:_Destroy(boost::function*,boost::function*)中的5 0x00000000004112df(
__第一个=0x62ef50,最后一个=0x62ed50)
at/usr/include/c++/5/bits/stl_construct.h:103
#标准中的6 0x0000000000410d16:_销毁(boost::function*,boost::function*)(uu first=0x62edd0,_uulast=0x62ed50)
at/usr/include/c++/5/bits/stl_construct.h:126
#std::_Destroy(boost::function*、boost::function*、std::alloct---Type继续,或q退出---
或&(uuu first=0x62edd0,uuu last=0x62ed50)
at/usr/include/c++/5/bits/stl_construct.h:151
#8 0x000000000040fac5在std::deque::_M_destroy_data_aux中(std:_deque_迭代器,std:_deque_迭代器)(this=0x7fffffffdaf0,_first=…,_last=…)
at/usr/include/c++/5/bits/deque.tcc:845
#std::deque::_M_destroy_数据中的9 0x000000000040e6e4(std:_deque_迭代器,std:_deque_迭代器,std::分配器常量&)(
this=0x7FFFFFDAF0,_first=…,_last=…)
at/usr/include/c++/5/bits/stl_deque.h:2037
#std::deque::~deque()中的10 0x000000000040d0c8,
__in_chrg=)at/usr/include/c++/5/bits/stl_deque.h:1039
#std::queue::~queue()中的11 0x000000000040b3ce(
这=0x7fffffffdaf0,uuu in_uchrg=)
at/usr/include/c++/5/bits/stl_queue.h:96
#线程池中的12 0x000000000040b6c0::~线程池(此=0x7FFFFFFFFAF0,
---键入以继续,或键入q以退出---
__main.cpp:63处的in_chrg=)
#main()中的13 0x0000000000408b60位于main.cpp:140处
我对此感到困惑,因为
进程
尚未超出范围,我正在将
boost::function
的副本传递给线程池进行处理


有什么想法吗

您似乎没有为其分配内存

extern char **environ;
任何地方。但这不是一个链接错误吗

将这一点缩减到最低限度会有很大帮助。这里有很多代码可能不需要重现问题

还有,这是什么:

    // supress exceptions

如果在加入线程时出现异常,那么您可能没有加入所有线程,并且在主退出后清理未加入线程的线程将导致错误。

堆栈跟踪表明您正在销毁未正确初始化的
std::function
(例如,被视为
std::function
的某个随机内存位置)或您两次销毁
std::function

问题是您的程序只推送到
任务
一次,但弹出五次,因此您从一个空的deque中删除元素,这是未定义的行为

<<代码> <代码>循环> PoLoLoad主/<代码>如果<代码>运行<代码>为false,并且<代码>运行可能是错误的,即使<代码> DeQue/COD>是空的。然后您无条件地选择代码> POP。您可以考虑修改<代码> POOLLUME < /代码>如下:

void pool_main() {

    // wait on condition variable
    // while the task is empty and the pool is still 
    // running
    boost::unique_lock<boost::mutex> lock(mutex);
    while (tasks.empty() && running) {
        condition.wait(lock);
    }

    // copy task locally and remove from the queue. this is
    // done within it's own scope so that the task object is destructed 
    // immediately after running the task. This is useful in the
    // event that the function contains shared_ptr arguments
    // bound via 'bind'
    if (!tasks.empty ()) {  // <--- !!!!!!!!!!!!!!!!!!!!!!!!
        auto task = tasks.front();
        tasks.pop();

        lock.unlock();

        // run the task
        try {
            std::cout << "running task" << std::endl;
            task();
        } catch (const std::exception &) {
            // supress
        }
    }

    // task has finished so increment count of availabe threads
    lock.lock();
    ++available;
};
void pool_main(){
//等待条件变量
//当任务为空且池仍为空时
//运行
boost::唯一的锁(互斥锁);
while(tasks.empty()&&running){
条件。等待(锁定);
}
//本地复制任务并删除
void pool_main() {

    // wait on condition variable
    // while the task is empty and the pool is still 
    // running
    boost::unique_lock<boost::mutex> lock(mutex);
    while (tasks.empty() && running) {
        condition.wait(lock);
    }

    // copy task locally and remove from the queue. this is
    // done within it's own scope so that the task object is destructed 
    // immediately after running the task. This is useful in the
    // event that the function contains shared_ptr arguments
    // bound via 'bind'
    if (!tasks.empty ()) {  // <--- !!!!!!!!!!!!!!!!!!!!!!!!
        auto task = tasks.front();
        tasks.pop();

        lock.unlock();

        // run the task
        try {
            std::cout << "running task" << std::endl;
            task();
        } catch (const std::exception &) {
            // supress
        }
    }

    // task has finished so increment count of availabe threads
    lock.lock();
    ++available;
};