Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/151.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++应用程序中隔离多线程问题。_C++_Multithreading - Fatal编程技术网

C++;多线程堆栈溢出 我试图在C++应用程序中隔离多线程问题。

C++;多线程堆栈溢出 我试图在C++应用程序中隔离多线程问题。,c++,multithreading,C++,Multithreading,下面的处理程序在辅助线程中被创建和“处理” struct Handler { void process(const std::vector<size_t> ops) { std::vector<size_t>::const_iterator iter = ops.cbegin(); while( iter != ops.cend() ) { processOperation( op );

下面的处理程序在辅助线程中被创建和“处理”

struct Handler 
{
    void process(const std::vector<size_t> ops)
    {
        std::vector<size_t>::const_iterator iter = ops.cbegin();
        while( iter != ops.cend() ) {
            processOperation( op );
        }
    }

    void processOperation(std::vector<size_t>::const_iterator& iter)
    {
        size_t op = *iter;
        iter++;

        switch( op ) {
            case frame_push : { 
                processOperation( iter );
                break;
            }
            case frame_pop : { 
                return;
            }
            default : { break; }
        }
    }
};
struct处理程序
{
无效过程(常数标准::向量操作)
{
std::vector::const_迭代器iter=ops.cbegin();
while(iter!=ops.cend()){
工艺操作(op);
}
}
void processOperation(std::vector::const_迭代器和iter)
{
尺寸=iter;
iter++;
开关(op){
外壳框架推送:{
工艺操作(iter);
打破
}
案例框架_pop:{
返回;
}
默认值:{break;}
}
}
};
正如您在上面所看到的,如果当前“op”等于frame_push,processOperation()将递归调用自身

我知道这里足够的递归操作会导致调用堆栈溢出。然而,当我在辅助线程而不是主线程上运行这个处理程序时,这种情况似乎发生得更快

似乎调用堆栈溢出的可能性并不是我这里唯一的问题。是否也存在重入问题


我真的非常感谢您的任何见解。谢谢

正如评论员Jeremy Friesner所说,线程的默认堆栈大小太小,导致溢出。我可以通过使用以下代码为boost::thread设置自定义堆栈大小(std::thread显然不存在此功能)来解决此问题:

boost::thread::attributes attributes;
attributes.set_stack_size( customStackSize );

boost::thread aThread( attributes, /* function binding here */ );
然而,正如Tsyvarev所建议的,这里真正的解决方案将是替换递归行为


谢谢大家

您正试图通过
while
循环和
递归两种方式迭代向量。您必须使用其中一种方法才能使代码正常工作。如果您尝试仅以一种方式实现,则不应出现任何堆栈溢出情况。下面是修改后的代码,它清楚地隔离了这两种类型的递归。希望这有助于解决您的问题

#include <iostream>
#include <vector>

using namespace std;

struct Handler 
{
    void processOperation(size_t& op)
    {
        std::cout << "Processing : " << op << std::endl;
        // TODO: Actual processing
    }

    void process(const std::vector<size_t> ops)
    {
        std::vector<size_t>::const_iterator iter = ops.cbegin();
        while( iter != ops.cend() ) {
            size_t op = *iter;
            processOperation(op);
            iter++;
        }
    }

    void processRecursive(std::vector<size_t>::const_iterator iter,
        std::vector<size_t>::const_iterator end)
    {
        if (iter != end)
        {
            size_t op = *iter;
            processOperation(op);
            processRecursive(++iter, end);
        }
    }
};

int main() {
    // your code goes here
    std::vector<size_t> ops;
    ops.push_back(1);
    ops.push_back(2);
    ops.push_back(3);
    ops.push_back(4);

    Handler h;
    h.process(ops);
    h.processRecursive(ops.cbegin(), ops.cend());
    return 0;
}
#包括
#包括
使用名称空间std;
结构处理程序
{
无效处理操作(大小测试与操作)
{

std::cout您成功消除的第一件事是“ops”的所有权,因为您通过值传递它,所以我们正在处理线程本地副本:

void process(const std::vector<size_t> ops)
但是好的。现在我们设置循环约束:

while( iter != ops.cend() ) {
但是,它不在递归调用的范围内,因此只有在我们离开递归调用时才会检查它

void processOperation(std::vector<size_t>::const_iterator& iter)
{
    size_t op = *iter;
    iter++;

    switch( op ) {
        case frame_push : { 
            processOperation( iter );
            break;
        }
        case frame_pop : { 
            return;
        }
        default : { break; }
    }
}
void处理操作(std::vector::const\u迭代器和iter)
{
尺寸=iter;
iter++;
开关(op){
外壳框架推送:{
工艺操作(iter);
打破
}
案例框架_pop:{
返回;
}
默认值:{break;}
}
}
在这个容器末尾的调用中没有代码。我猜frame_push和frame_pop允许您为任何默认情况创建范围,因此您需要递归

如果这就是目的,那么最好实现自己的帧堆栈

#include <vector>
#include <iostream>
#include <thread>

enum Operands { frame_push, frame_pop, other };

struct Frame {};

struct Handler
{
    size_t maxDepth, pushCount, popCount;

    Handler() : maxDepth(0), pushCount(0), popCount(0) {}

    void handle(const std::vector<Operands> ops_)
    {
        std::vector<Frame> stack;
        stack.reserve(256);
        stack.emplace_back(); // Create a default Frame
        for (auto iter = ops_.cbegin(); iter != ops_.cend(); ++iter) {
            switch (*iter) {
                case frame_push:
                    // make a copy of the current frame,
                    // remove the 'stack.back()' if new frames should
                    // start empty
                    ++pushCount;
                    stack.emplace_back(stack.back());
                    maxDepth = std::max(maxDepth, stack.size());
                break;
                case frame_pop:
                    stack.pop_back();
                    ++popCount;
                break;
                default: {
                    Frame& frame = stack.back();
                    (void)frame;
                }
                break;
            }
        }
        std::this_thread::yield();
        std::cout << "ops len " << ops_.size()
            << ", pushCount " << pushCount
            << ", popCount " << popCount
            << ", maxDepth " << maxDepth
            << std::endl;
        std::this_thread::yield();
    }
};

int main()
{
    std::vector<Operands> ops = {
        frame_push, other, other,
            frame_push, other, frame_pop,
            other,
            frame_push, frame_pop,
            other,
            frame_push,
                frame_push, other, other, frame_pop,
            frame_pop,
        frame_pop
    };

    Handler h;
    std::thread t1(&Handler::handle, &h, ops);
    t1.join();
}
#包括
#包括
#包括
枚举操作数{frame_push,frame_pop,other};
结构框架{};
结构处理程序
{
大小\u t最大深度、pushCount、popCount;
处理程序():maxDepth(0)、pushCount(0)、popCount(0){
无效句柄(常量标准::向量运算)
{
std::向量堆栈;
堆栈保留(256);
stack.emplace_back();//创建默认帧
对于(自动iter=ops_uu.cbegin();iter!=ops_uu.cend();++iter){
开关(*iter){
箱框推:
//制作当前帧的副本,
//如果需要新帧,请删除“stack.back()”
//空头支票
++推送计数;
stack.emplace_back(stack.back());
maxDepth=std::max(maxDepth,stack.size());
打破
箱框弹出:
stack.pop_back();
++流行人数;
打破
默认值:{
Frame&Frame=stack.back();
(空)框架;
}
打破
}
}
std::this_thread::yield();

std::cout在许多操作系统上,主线程堆栈的默认大小比其他线程堆栈的默认大小大得多。您可以检查线程的堆栈大小,看看这是否是您看到所看到内容的原因。嗯,谢谢,很好的提示!您能给我指一下如何公开此信息的任何文档吗。我很抱歉我在XCode中工作。这个递归可以很容易地使用cycle
线性化,而(depth)
,其中
depth
是您原始的递归深度。我似乎得到了相同的堆栈大小(524288字节)对于主线程和辅助线程。尽管如此,代码似乎在主线程上运行,而不是在辅助线程上运行。我正在为测试目的展开我的递归……但在简化的测试实现之外,这可能相当困难
void processOperation(std::vector<size_t>::const_iterator& iter)
{
    size_t op = *iter;
    iter++;

    switch( op ) {
        case frame_push : { 
            processOperation( iter );
            break;
        }
        case frame_pop : { 
            return;
        }
        default : { break; }
    }
}
#include <vector>
#include <iostream>
#include <thread>

enum Operands { frame_push, frame_pop, other };

struct Frame {};

struct Handler
{
    size_t maxDepth, pushCount, popCount;

    Handler() : maxDepth(0), pushCount(0), popCount(0) {}

    void handle(const std::vector<Operands> ops_)
    {
        std::vector<Frame> stack;
        stack.reserve(256);
        stack.emplace_back(); // Create a default Frame
        for (auto iter = ops_.cbegin(); iter != ops_.cend(); ++iter) {
            switch (*iter) {
                case frame_push:
                    // make a copy of the current frame,
                    // remove the 'stack.back()' if new frames should
                    // start empty
                    ++pushCount;
                    stack.emplace_back(stack.back());
                    maxDepth = std::max(maxDepth, stack.size());
                break;
                case frame_pop:
                    stack.pop_back();
                    ++popCount;
                break;
                default: {
                    Frame& frame = stack.back();
                    (void)frame;
                }
                break;
            }
        }
        std::this_thread::yield();
        std::cout << "ops len " << ops_.size()
            << ", pushCount " << pushCount
            << ", popCount " << popCount
            << ", maxDepth " << maxDepth
            << std::endl;
        std::this_thread::yield();
    }
};

int main()
{
    std::vector<Operands> ops = {
        frame_push, other, other,
            frame_push, other, frame_pop,
            other,
            frame_push, frame_pop,
            other,
            frame_push,
                frame_push, other, other, frame_pop,
            frame_pop,
        frame_pop
    };

    Handler h;
    std::thread t1(&Handler::handle, &h, ops);
    t1.join();
}