简体   繁体   中英

C++ Stack Overflow Exception, possibly due to recursion

I have some code which is working as it should. However, sometimes my program has to close due to an error. I have tried to debug this error but am having several problems when I do this.

When I run in debug, I get a stack overflow error very soon after I start the program, much sooner than when I get an error in release.

I have narrowed down the point at which the error is thrown in debug, at it is when this recursive function is called the 3570th time.

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

Any ideas about why the program is crashing here and why it only crashes here in debug?

Anyway, getting back to the original problem, I have narrowed down the place at which that fails.

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

It fails when calling aggregateStepTwo after a certain number of calls. It could potentially recursively call it 1,000,000 times. Is this another stack overflow?

If so how do I get rid of the stack overflows?

Thanks Rob

You have tail recursion. It is usually very simple to replace this kind of recursion with an iterative algorithm. Here's a naive approach that just rewrites your recursion as an infinite loop that breaks in the same places where the recursion would stop.

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++;
  }
}

This should work.

Now, if you dislike break s, a more "elegant" solution (debatable) could be obtained from the following observations:

  1. On the first iteration, the assignment depends only on the value of index
  2. Each subsequent iteration depends on index 's root and a relation involving index 's parent and rank+1 .

So the first looks like a special case. The others rely on the same expression involving index and index 's parent. So if we take the first case out of the loop, we get the following algorithm:

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

I'm actually surprised the compiler didn't convert this recursion into a loop automatically. Are you not compiling with optimization flags or am I expecting too much from compilers?

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM