Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.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++ 从线程引发异常未给出预期结果_C++_Multithreading_Exception_Boost - Fatal编程技术网

C++ 从线程引发异常未给出预期结果

C++ 从线程引发异常未给出预期结果,c++,multithreading,exception,boost,C++,Multithreading,Exception,Boost,在下面的代码片段中,我试图在重新抛出相同的异常后捕获异常,但无法实现相同的异常。但我不确定出了什么问题,因为我已经通过current_exception()保留了当前的teptr状态。线程是在连续循环中运行的,所以一旦它的值达到较大的2,就会执行catch块,并且控制到达循环之外,但正如预期的那样,我无法在第一次尝试本身时到达另一个catch块 #include <boost/thread.hpp> #include <boost/thread/scoped_thread.hp

在下面的代码片段中,我试图在重新抛出相同的异常后捕获异常,但无法实现相同的异常。但我不确定出了什么问题,因为我已经通过current_exception()保留了当前的teptr状态。线程是在连续循环中运行的,所以一旦它的值达到较大的2,就会执行catch块,并且控制到达循环之外,但正如预期的那样,我无法在第一次尝试本身时到达另一个catch块

#include <boost/thread.hpp>
#include <boost/thread/scoped_thread.hpp>
#include <boost/chrono.hpp>
#include <iostream>
#include <boost/exception/all.hpp>
#include <exception>
using namespace std;
boost::exception_ptr teptr;

class myexception : public exception
{
    virtual const char* what() const throw()
    {
        return "My exception happened";
    }
} myex;

class ABC
{
public:
    void start();

};

void ABC::start()
{
    int i = 0;
    cout << "running the thread" << std::endl;

    while (1)
    {
        try
        {
            std::cout << "value of " << i << '\n';

            if (i > 2)
            {
                throw  boost::enable_current_exception(myex);
            }
            i++;
        }
        catch (exception& e)
        {
            cout << "actual exception is" << e.what() << '\n';
            teptr = boost::current_exception();
            break;
            //throw myex;
        }
    }
}

int main()
{
    ABC abc;
    boost::thread thread_point;

    while (1)
    {
        boost::thread thread_point;
        thread_point = boost::thread(&ABC::start, abc);

        if (teptr) {

            try {
                boost::rethrow_exception(teptr);
            }
            catch (const std::exception &ex)
            {
                std::cerr << "Thread exited with exception: " << ex.what() << "\n";
                exit(0);
            }
        }
    }
}
#包括
#包括
#包括
#包括
#包括
#包括
使用名称空间std;
boost::异常\u ptr teptr;
类myexception:公共异常
{
虚拟常量char*what()常量throw()
{
返回“我的异常发生”;
}
}myex;
ABC班
{
公众:
void start();
};
void ABC::start()
{
int i=0;

cout更新我的答案有缺陷且有错误,请参见sehe的评论

我不确定您的最终目标是什么,但我想知道如何处理线程抛出。是的,您可以绕过编译器无法在线程之间抛出Boost异常的问题

#include <boost/thread.hpp>
#include <boost/thread/scoped_thread.hpp>
#include <boost/chrono.hpp>
#include <iostream>
#include <boost/exception/all.hpp>
#include <exception>

boost::exception_ptr teptr;
class myexception: public std::exception
{
    virtual const char* what() const throw()
    {
        return "My exception happened";
    }
} myex;


class ABCc
{
public:
    void start();
};

void ABCc::start()
{  
    int i=0;
    std::cout<<"running the thread"<<std::endl;

    while (1)
    {
        try
        {
            std::cout << "value of "<<i << '\n';

            if(i>2)
            {
                throw  boost::enable_current_exception(myex);
            }
            i++;
        }
        catch (std::exception& e)
        {
            std::cout << "actual exception is"<<e.what() << '\n';
            teptr=boost::current_exception();
            break;
            // where were you going here???????
            //throw myex;
        } 
    }
}

int main()
{
    ABCc abc;
    boost::thread thread_point;
    thread_point = boost::thread(&ABCc::start,abc);
    while(1)
    {
        if (teptr) {
            try {
                boost::rethrow_exception(teptr);
            }
            catch(const std::exception &ex) {
                std::cerr << "Thread may have exited; exception thrown: " << ex.what() << "\n";
                break;
            }
        } 
    } 
    std::cout << "exception should have been caught" << std::endl;
    return 0;
}   
#包括
#包括
#包括
#包括
#包括
#包括
boost::异常\u ptr teptr;
类myexception:public std::exception
{
虚拟常量char*what()常量throw()
{
返回“我的异常发生”;
}
}myex;
ABCc类
{
公众:
void start();
};
void ABCc::start()
{  
int i=0;

std::cout更新我的答案有缺陷且有错误,请参见sehe的评论

我不确定您的最终目标是什么,但我想知道如何处理线程抛出。是的,您可以绕过编译器无法在线程之间抛出Boost异常的问题

#include <boost/thread.hpp>
#include <boost/thread/scoped_thread.hpp>
#include <boost/chrono.hpp>
#include <iostream>
#include <boost/exception/all.hpp>
#include <exception>

boost::exception_ptr teptr;
class myexception: public std::exception
{
    virtual const char* what() const throw()
    {
        return "My exception happened";
    }
} myex;


class ABCc
{
public:
    void start();
};

void ABCc::start()
{  
    int i=0;
    std::cout<<"running the thread"<<std::endl;

    while (1)
    {
        try
        {
            std::cout << "value of "<<i << '\n';

            if(i>2)
            {
                throw  boost::enable_current_exception(myex);
            }
            i++;
        }
        catch (std::exception& e)
        {
            std::cout << "actual exception is"<<e.what() << '\n';
            teptr=boost::current_exception();
            break;
            // where were you going here???????
            //throw myex;
        } 
    }
}

int main()
{
    ABCc abc;
    boost::thread thread_point;
    thread_point = boost::thread(&ABCc::start,abc);
    while(1)
    {
        if (teptr) {
            try {
                boost::rethrow_exception(teptr);
            }
            catch(const std::exception &ex) {
                std::cerr << "Thread may have exited; exception thrown: " << ex.what() << "\n";
                break;
            }
        } 
    } 
    std::cout << "exception should have been caught" << std::endl;
    return 0;
}   
#包括
#包括
#包括
#包括
#包括
#包括
boost::异常\u ptr teptr;
类myexception:public std::exception
{
虚拟常量char*what()常量throw()
{
返回“我的异常发生”;
}
}myex;
ABCc类
{
公众:
void start();
};
void ABCc::start()
{  
int i=0;

std::cout您的程序不同步地从多个线程同时访问变量
teptr
(以及
myex
)。行为未定义

更糟糕的是,您正在跟踪
线程\u点
并创建许多未连接的线程。实际上,您正在运行共享相同全局数据的无限线程

我想你真的在寻找
future
s,它允许你从任何地方返回值或异常。所有异常处理魔法都为你完成了:

#include <thread>
#include <future>
#include <iostream>
#include <sstream>

struct ABC {
    int task(int until) {
        for (int i = 0; i<10; ++i) {
            if (i > until) {
                std::ostringstream oss;
                oss << "My exception happened in thread " << std::this_thread::get_id() << " at i=" << i;
                throw std::runtime_error(oss.str());
            }
        }

        return 42;
    }
};

int main() {
    for (int runs = 0; runs < 10; ++runs) {
        ABC abc;
        std::future<int> result = std::async(&ABC::task, &abc, rand()%20);

        try {
            std::cout << "Task returned " << result.get() << "\n";
        } catch (const std::exception &ex) {
            std::cout << "Task exited with exception: " << ex.what() << "\n";
            std::cerr << "Thread exited with exception: " << ex.what() << "\n";
        }
    }
}

您的程序不同步地从多个线程同时访问变量
teptr
(以及
myex
)。行为未定义

更糟糕的是,您正在跟踪
线程\u点
并创建许多未连接的线程。实际上,您正在运行共享相同全局数据的无限线程

我想你真的在寻找
future
s,它允许你从任何地方返回值或异常。所有异常处理魔法都为你完成了:

#include <thread>
#include <future>
#include <iostream>
#include <sstream>

struct ABC {
    int task(int until) {
        for (int i = 0; i<10; ++i) {
            if (i > until) {
                std::ostringstream oss;
                oss << "My exception happened in thread " << std::this_thread::get_id() << " at i=" << i;
                throw std::runtime_error(oss.str());
            }
        }

        return 42;
    }
};

int main() {
    for (int runs = 0; runs < 10; ++runs) {
        ABC abc;
        std::future<int> result = std::async(&ABC::task, &abc, rand()%20);

        try {
            std::cout << "Task returned " << result.get() << "\n";
        } catch (const std::exception &ex) {
            std::cout << "Task exited with exception: " << ex.what() << "\n";
            std::cerr << "Thread exited with exception: " << ex.what() << "\n";
        }
    }
}


在分配给
teptr
之前,这里没有什么可以停止
if(teptr)
运行的。你是不是想在某个地方执行
join
操作?那里不需要join。你怎么会这样想?join正在阻塞,需要等待线程完成。这里没有什么可以停止
if(teptr)
在分配到
teptr
之前运行。你是不是想在某个地方执行
连接
?那里不需要连接。你怎么会这样认为?连接正在阻塞,需要等待线程完成。如果你坚持使用Boost,这是使用Boost的c++03版本。感谢sehe提供此解决方案。我已经更新了我的impleme链接下方的提示。通常在线程内部,我需要捕获由第三方库引发的异常,并再次需要从catch块中重新引用该异常,以便可以通过外部接口传播。请对此进行查看并提出建议。以下是错误:。在抛出“boost::exception\u detail::clone\u impl”Hi@sehe”实例后调用了terminate,这是一个非常优雅的答案。我又学了一次。我留下了我的答案,因此可以看到错误,谢谢。如果您坚持使用boost,下面是使用boost的c++03版本,谢谢sehe的帮助他的解决方案。我已经在下面的链接上更新了我的实现。通常在线程内部,我需要捕获第三方库引发的异常,并且再次需要从catch块中重新引用该异常,以便可以通过外部接口传播。请请看一下并提出建议。错误如下:。在抛出“boost::exception\u detail::clone\u impl”Hi@sehe的实例后调用terminate,这是一个非常优雅的答案。我又学了一次。我留下了我的答案,所以可以看到错误,谢谢。此代码仍然具有竞争条件。data race实际上是-while循环完全可能是无限的,并且永远不会检测到
teptr
中的更改(为什么会这样?它不是
易失性的
,并且没有内存障碍。编译器在单次加载后知道值,不需要生成任何其他加载)。此代码仍然具有争用条件。数据争用实际上是-while循环完全可能是无限的,并且永远不会检测到
teptr
中的更改(为什么会这样?它不是
易失性的
,并且没有内存障碍。编译器在单次加载后知道值,不需要生成任何其他加载).