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();
}