function readOnly(count){ }
Starting November 20, the site will be set to read-only. On December 4, 2023,
forum discussions will move to the Trailblazer Community.
+ Start a Discussion
Ron9Ron9 

catching Stack depth limit reached

Hi

Can anyone help on how to detect that I'm about to bang against the Stack depth governor limit?

 

I was hoping to use the Limits... method to detect whether I was about to hit the limit, but I can't find anything related to the stack depth.

 

Has anyone dealt with this before?

 

Best regards

Ronni

Best Answer chosen by Admin (Salesforce Developers) 
sfdcfoxsfdcfox

Wouldn't it be more economical to simply detect the infinite recursion yourself?

 

public class TreeNode {
  public TreeNode[] children;
  public integer gethashcode() {
    // Figure out a non-unique serial identifier
  }
  public integer equals(object o) {
    // Figure out how your node is equal or not
  }
  public boolean validate() {
    set<treenode> processednodes = new set<treenode>();
    return validate(processednodes,this);
  }
  boolean validate(set<treenode> nodes, treenode current) {
    if( nodes.contains(current) ) {
      return false; // we've been here before
    }
    nodes.add( current ); // drop a breadcrumb
    for( treenode n:children ) {
      boolean result = validate(nodes,n); // check each child, this will recurse
      if( !result ) { // downstream loop detected, go back
        return false;
      }
    }
    return true;
  }
}

Caling "validate()" on the root node will cause a recursive check that will check for a duplicated node (which would lead to an infinite loop). As a bonus, your stack will only go as deep as there are tree levels. Depending on your implementation, you might have to change a few things around, but this would be an ideal recursive function that checks for infinite loops. I personally wouldn't do it this way, as a simple non-recursive loop with a lifo stack would allow much deeper recursion, but it's a matter of choice.

 

Edit: No matter how you do it, I'd propose you avoid a hard limit recursion variable; depending on language limitations means that a future release might break your code (say, the maximum recursion depth is moved to 500 for performance reasons).

All Answers

sandeep@Salesforcesandeep@Salesforce

As such there is no other method to determine stack limit about to reach. so you can do one thing please create a class  with one 

integer static property. 

and if you need to deal with two triggers which call to each others then increase this counter and when it get 16 please stop execution further.

 

This will solve your problem.

 

Please mark answer as solution and give me kudos if it was help ful

Ron9Ron9
Hey sandeep,
Thank you for your answer, but is 16 always the limit? I ask because I discovered this issue given the error message " Maximum stack depth reached: 1001 "
I should say this is caused be a method called form a VF controller. Can the limit be 1000 in some cases?
sfdcfoxsfdcfox

Don't confuse stack limits with recursive trigger limits. The 16 limit refers to a DML operation that causes another DML operation (via triggers); you can only go 16 DML calls deep before your code will bail out. The stack, on the other hand, is a memory structure that keeps track of your function calls. This has a separate limit (much higher), and is reached through recursive function calls. Consider the following implementation of n! (factorial numbers):

 

public integer fn(integer x) {
  if(x==1) {
    return 1;
  }
  return x * fn(x-1);
}

If you call fn(1), the result is 1; the maximum stack depth reached is 1. If you call fn(3), the result is 3 * 2 * 1, or 6, and the total stack depth here is 3 (fn, once called, calls itself two more times to derive the final answer). Calling fn(1001) would result in a mathematical overflow, but if it didn't, the stack would reach a depth of 1001.

 

Each time you call a function, the "instruction pointer" for where that function was called is placed on the stack. When the called function returns, the instruction pointer reloads that stored location and continues from that point. Most modern developers are unaware of this feature of programming because it has been abstracted away by the language. In traditional 80x86 machine code, it was important to know how much stack space remained, because the system could only have up to 32767 recursive function calls ("local variables" also resided on the stack, and would reduce the total maximum recursive function calls one could make). In modern languages, the stack is managed for you, and you have no way to avoid this limitation short of creating your own stack structure and some fairly complex logic (plus, object-oriented programming makes this virtually impossible).

 

In Apex Code, you are limited to a maximum depth of 1000 recursive function calls. The usual way one would reach this limit is by either by calling a function that calls itself recursively, or, more likely, calling a function ("A") that calls a second function ("B") that in return calls function A again (thus, a possibly infinite loop).

 

You should analyze the functions involved in your code and see if there's a function that calls itself recursively, or calls another function that could call the first one again (or, it may even be 3 or more functions). The most usual cause I've observed with this limit is when implementing custom getter functions, where a getter for A calls the getter for B, which calls the getter for A. It is easy to track down once you know what you are looking for, but there are very few good examples of how this occurs and/or how to fix it out there on the forums or the Internet. Here's an (obvious) example:

 

public integer a { get { return b == null ? 1 : b + 1; } set; }
public integer b { get { return a == null ? 1 : a + 1; } set; }

What will happen if you try to access A or B? If you access, for example, A, it will call the getter for B (to check b == null), which in turn will call the getter for A (to check a == null), which will call the getter for B (to check b == null)... and so on recursively until the stack is exhausted. The solution to such a problem is typically to include a backing variable:

 

integer a1, b1;
public integer a { get { return b1 == null ? 1 : b1 + 1; } set { a1 = value; } }
public integer b { get { return a1 == null ? 1 : a1 + 1; } set { b1 = value; } }

 

This eliminates the possibility that the getters will be called recursively. Note that the value of a or b still depends on which one is accessed first, etc, but that's an exercise for another day.

RonniRonni

Thank you sfdcfox for you very thorough answer.

Great you clear up the misunderstanding with the recursive trigger limit because this is the stack limit in question.

I'm aware that this is caused by recursive method calls as this is done by design not by accident. I'm performing a depth first traversal of a tree graph. But this graph is based on user created records and can be made with circles in the references. Therefore I want to performe a check ensuring that such a fault circle does not end in a "stack limit reached" error.

 

Is the surgestion from Sandeep really the most graceful solution, with a static integer counter and a hard-coded limit of 1000?

 

/Ronni

sfdcfoxsfdcfox

Wouldn't it be more economical to simply detect the infinite recursion yourself?

 

public class TreeNode {
  public TreeNode[] children;
  public integer gethashcode() {
    // Figure out a non-unique serial identifier
  }
  public integer equals(object o) {
    // Figure out how your node is equal or not
  }
  public boolean validate() {
    set<treenode> processednodes = new set<treenode>();
    return validate(processednodes,this);
  }
  boolean validate(set<treenode> nodes, treenode current) {
    if( nodes.contains(current) ) {
      return false; // we've been here before
    }
    nodes.add( current ); // drop a breadcrumb
    for( treenode n:children ) {
      boolean result = validate(nodes,n); // check each child, this will recurse
      if( !result ) { // downstream loop detected, go back
        return false;
      }
    }
    return true;
  }
}

Caling "validate()" on the root node will cause a recursive check that will check for a duplicated node (which would lead to an infinite loop). As a bonus, your stack will only go as deep as there are tree levels. Depending on your implementation, you might have to change a few things around, but this would be an ideal recursive function that checks for infinite loops. I personally wouldn't do it this way, as a simple non-recursive loop with a lifo stack would allow much deeper recursion, but it's a matter of choice.

 

Edit: No matter how you do it, I'd propose you avoid a hard limit recursion variable; depending on language limitations means that a future release might break your code (say, the maximum recursion depth is moved to 500 for performance reasons).

This was selected as the best answer
Ron9Ron9
Thanks again sfdcfox
I do agree that detecting the circle is the better solution. Thank you for your help.
/Ronni
Sachin10Sachin10
@SFDCFOX
Excellent explanation.I was googling for the same and found this link.trust me you saved a lot of time :)
Many thanks and God bless!