Friday, February 17, 2012

Get the callstack without the need of breakpoints

Normally, when you debug a issue, you use the debugger and breakpoints. That's fine, but sometimes you need to debug bugs that triggers randomly and you need to check the call stack for more information or even log the call stack to a table for later inspections. Here is how to do that. Create a new class or use your existing tool class and insert the following method:

static str getCallStack(boolean _showInfo = false)
{
   xSession xSession = new xSession();
   container callStack = xSession::xppCallStack();
   str text;
   int i;

   str convert2string(anytype _value, int variation = 0)
   {
      switch (typeof(_value))
      {
         case Types::String :
            return _value;
         case Types::Real :
            return num2str(_value, 10, 4, 1, 0);
         case Types::Integer :
            return int2str(_value);
         case Types::Date :
            if (variation == 0)
               return date2str(_value, 321, 2, 3, 2, 3, 4 );
            else if (variation == 1)
               return date2str(_value, 321, 2, 1, 2, 1, 2 );
         case Types::Enum :
               return enum2str(_value);
      }
   }

   for (i = 1; i < conLen(callStack); i+=2)
   {
      if(_showInfo)
         info( "Path: " + convert2string(conPeek(callStack, i)) + " Line: " + convert2string(conPeek(callStack, i+1)));

      text += ("Path: " + convert2string(conPeek(callStack, i)) + " Line: " + convert2string(conPeek(callStack, i+1)) + "\n");
   }
   return text;
}


Then in your class where you want to get the call stack:

Example
...
   try
   {
      ...
   } catch (..)
   {
       MyToolClass:: getCallStack(true);
   }
 ...

BTW: If the code are executed in a thread or at the AOS, you should call getCallStack with false and use the returned string instead.

1 comment: