我有一些正常工作的代码。但是,有时我的程序必须因错误而关闭。我试图调试此错误,但在执行此操作时遇到了一些问题。
当我在调试中运行时,我在启动程序后很快就会出现堆栈溢出错误,这比我在发布时出错时要快得多。
我缩小了调试时抛出错误的点,就是在第3570次调用此递归函数时。
void setRankAbove(vector<nodeStructure> &allNodes, int index, int rankToSet) {
if (rankToSet>=allNodes[index].rank) {
allNodes[index].rank = rankToSet;
if (allNodes[index].root != index) {
setRankAbove(allNodes, allNodes[index].parent, rankToSet + 1,debug);
}
}
}
有关程序崩溃原因以及为什么它只会在调试中崩溃的任何想法?
无论如何,回到最初的问题,我已经缩小了失败的地方。
vector<vector<double>> backwardsAggregation(int inputRows, int inputCols, vector<vector<double>> &localCostsStepOne, vector<nodeStructure> &nodeMST,float sigma,bool debug) {
// create 2D array of local costs step 2
vector<double> localOneDim(inputCols);
vector<vector<double>> localCostsRootToLeaf(inputRows, localOneDim);
// factors defined in paper
double nodeFactor = (1 - exp(-1 / (sigma*sigma)));
double parentFactor = exp((double)(-0.5) / (sigma*sigma));
cout << "Step 3.2.1" << endl;
try{
aggregateStepTwo(nodeMST, nodeMST[0].root, localCostsStepOne, localCostsRootToLeaf, parentFactor, nodeFactor, debug, 0);
}
catch (const std::exception & ex) {
cout<< "exception"<< endl;
cout << ex.what() << endl;
}
cout << "Step 3.2.2" << endl;
return localCostsRootToLeaf;
}
在一定数量的调用后调用aggregateStepTwo时失败。它可能会递归地称它为1,000,000次。这是另一个堆栈溢出吗?
如果是这样,我如何摆脱堆栈溢出?
由于 罗布
答案 0 :(得分:1)
你有尾递归。通过迭代算法替换这种递归通常非常简单。这是一种天真的方法,只是将递归重写为无限循环,在递归停止的相同位置中断。
void setRankAbove(vector<nodeStructure> &allNodes, int index, int rankToSet) {
while (1) {
if (rankToSet < allNodes[index].rank) {
break;
}
allNodes[index].rank = rankToSet;
if (allNodes[index].root == index) {
break;
}
index = allNodes[index].parent;
rankToSet++;
}
}
这应该有用。
现在,如果您不喜欢break
,可以从以下观察中获得更“优雅”的解决方案(值得商榷):
index
index
的根以及涉及index
的父级和rank+1
的关系。所以第一个看起来像一个特例。其他人依赖于涉及index
和index
父母的相同表达。因此,如果我们将第一个案例排除在循环之外,我们将得到以下算法:
void setRankAbove(vector<nodeStructure> &allNodes, int index, int rankToSet) {
if (rankToSet < allNodes[index].rank) {
return;
}
allNodes[index].rank = rankToSet++;
int parent = allNodes[index].parent;
while (allNodes[index].root != index && rankToSet >= allNodes[parent].rank) {
index = parent;
allNodes[index].rank = rankToSet++;
parent = allNodes[index].parent;
}
}
我真的很惊讶编译器没有自动将这种递归转换为循环。你是不是在编译优化标志,还是我对编译器的期望过高?