You need a view of what the stack looks like at any particular point in your application. However, you do not have an exception object from which to obtain this stack trace.
Use the following line of code to obtain a stack trace at any point in your application:
string currentStackTrace = System.Environment.StackTrace;
The variable currentStackTrace
now contains the
stack trace at the location where this line of code was executed.
A good use of the Solution is tracking down stack overflow problems. You can obtain the current stack trace at various points in your application and then calculate the stack depth. This depth calculation can then be logged to determine when and why the stack is overflowing or potential trouble spots where the stack may grow very large.
It is very easy to
obtain a stack trace using the
System.Environment.StackTrace
property.
Unfortunately, this stack trace also lists three methods defined in
the System.Environment
class that are called when
you use the Environment.StackTrace
property. The
returned stack trace, using this method, will look something like the
following:
at System.Environment.GetStackTrace(Exception e) at System.Environment.GetStackTrace(Exception e) at System.Environment.get_StackTrace( ) at Chapter_Code.Class1.ObtainingStackTrace( ) in c:ook cs cookbook est.cs:line 260 at Chapter_Code.Class1.Main(String[] args) in c:ook cs cookbookmain.cs:line 78
The first three items in the stack trace are method calls that we are not interested in. To fix this, we can write the following method to find and remove these items from the stack trace:
public static string GetStackTraceInfo(string currentStackTrace) { string firstStackTraceCall = "System.Environment.get_StackTrace( )"; int posOfStackTraceCall = currentStackTrace.IndexOf(firstStackTraceCall); return (currentStackTrace.Substring(posOfStackTraceCall + firstStackTraceCall.Length)); }
This method is called using the following line of code:
string stackTraceInfo = GetStackTraceInfo(System.Environment.StackTrace);
The second line in the
GetStackTraceInfo
method creates and initializes a
string variable to the first called StackTrace
method—which is actually a call to the get
portion of the StackTrace
property. This variable
is used in the third line to obtain its starting position in the
complete stack trace string. The final line of code grabs the end of
the complete stack trace string, starting at the ending of the first
called StackTrace
method. The
FinalStackTrace
variable now contains the
following string:
at Chapter_Code.Class1.ObtainingStackTrace( ) in c:ook cs cookbook est.cs:line 260 at Chapter_Code.Class1.Main(String[] args) in c:ook cs cookbookmain.cs:line 78
This is the current stack trace at the point in the code where the
Environment.StackTrace
method was called.
Now that we have a stack trace of our code, we can calculate the
stack depth at the point where we call
Environment.StackTrace
. The following code uses a
regular expression to determine the depth of a stack
trace:
using System; using System.Text.RegularExpressions; public static int GetStackTraceDepth(string currentStackTrace) { string firstStackTraceCall = "System.Environment.get_StackTrace( )"; int posOfStackTraceCall = currentStackTrace.IndexOf(firstStackTraceCall); string finalStackTrace = currentStackTrace.Substring(posOfStackTraceCall + firstStackTraceCall.Length); MatchCollection methodCallMatches = Regex.Matches(finalStackTrace, @"sats.*(sins.*:linesd*)?"); return (methodCallMatches.Count); }
This regular expression captures every method call in the stack trace string. Note that, if the correct symbols are located for our assembly, the stack trace might look like this:
at Chapter_Code.Class1.ObtainingStackTrace( ) in c:ook cs cookbook est.cs:line 260 at Chapter_Code.Class1.Main(String[] args) in c:ook cs cookbookmain.cs:line 78
However, if the correct symbols cannot be found, the stack trace string will look similar to the following:
at Chapter_Code.Class1.ObtainingStackTrace( ) at Chapter_Code.Class1.Main(String[] args)
The file and line numbers are not displayed in this case, and the regular expression must take this into account.
To get a count of the stack depth, use the Count
property of the MatchCollection
object to give the
total number of method calls in the stack. In addition, we can obtain
each individual method call as an independent string by iterating
through the MatchCollection
object. The code to do
this is:
Console.WriteLine("-------------"); foreach(Match m in MethodCallMatches) { Console.WriteLine(m.Value + System.Environment.NewLine + "-------------"); }
This code will display the following:
------------- at Chapter_Code.Class1.ObtainingStackTrace( ) in c:ook cs cookbook est.cs:line 260 ------------- at Chapter_Code.Class1.Main(String[] args) in c:ook cs cookbookmain.cs:line 78 -------------
Each method and its information are contained within a
Match
object within the
MatchCollection
object.
The Environment.StackTrace
method can be useful as
a debugging tool. You can see at various points in your application
which methods have been called and their calling order. This can come
in very handy when creating and debugging an application that uses
recursion. In addition, you can also keep track of the stack depth by
using the Environment.StackTrace
property.