Click here to Skip to main content
13,148,211 members (52,662 online)
Click here to Skip to main content
Add your own
alternative version

Tagged as

Stats

6.9K views
3 bookmarked
Posted 13 Feb 2014

Help Yourself in Debugging (Part 3) StackTrace and Caller Information Attribute

, 13 Feb 2014
Rate this:
Please Sign up or sign in to vote.
Help yourself in debugging (Part 3) StackTrace and Caller Information attribute

Read the below post related to the same topics:

  1. Help yourself in Debugging by using Call Stack and Immediate Window
  2. Help Yourself in Debugging (Part-2) using Breakpoint/Tracepoint

This post is about two features in C# Caller Information Attribute and StackTrace class, which are helpful to get information at runtime from where the call came, i.e., both provide information about caller. As the purpose of both is the same but there is significant difference between both of them. Information provided by both can be used by developer application to provide trace information.

Before starting with StackTrace and Caller information, the following image shows structure of the code.

So the project is divided in three layers, UI, Business and DataLayer.

Front Layer Code

class Program
    {
        //Program p = new Program();

        public int i = 10;
        public static void Main(string[] args)
        {
            try
            {
                var str = (new BusinessEmployee()).GetEmployeeList();
                Console.WriteLine(str);
                Console.ReadLine();
            }
            catch (Exception ex)
            {
                global::System.Windows.Forms.MessageBox.Show(ex.Message);
            }
        }
    }

As you see in the above code, the Font layer is calling "GetEmployeeList" method to get a list of all employees.

BusinessLayer Code

public class BusinessEmployee
{
    private readonly DataEmployee dataEmployee;

    public BusinessEmployee()
    {
        dataEmployee = new DataEmployee();
    }

    public  void GetEmployeeList()
    {
        dataEmployee.GetEmployeeList();
    }
}

In this layer, Business class is calling DataLayer to get employee list from the database.

DataLayer Code

public class DataEmployee
{
    //Data layer class for employee
    public  void GetEmployeeList()
    {
        //code goes here for retrieving from DATABASE
    }
}

This layer returns employee list, but for the example, it's returning exception.

StackTrace

Class in C# part of System.Diagnostics namespace which provides information same as Call Stack window (Read more about Call stack window ) at runtime.

To understand it in a better way, let's consider change in the above code in DataLayer.

//Data layer class for employee
public string GetEmployeeList()
{
    //// get call stack
    StackTrace stackTrace = new StackTrace(true);

    StringBuilder sb = new StringBuilder();

    foreach (StackFrame frame in stackTrace.GetFrames())
    {
        sb.AppendLine(" Method Name: " + frame.GetMethod().Name +
             " File Name:" + frame.GetMethod().Module.Name + " Line No: " +
                           frame.GetFileLineNumber());
    }

    return sb.ToString();
}

As you can see in code, it creates StackTrace class and when creating new object of class "true" is passed as argument to the constructor of StackTrace class for capturing the file name, line number, and column number.

After the object gets created, GetFrames method is used to get information about each frame (each method call is represented by one frame) and finally each frame detail is appended using StringBuilder, then it is displayed by front end.

Following is the output that gets received once the code runs:

So output prints each call made from one layer to another if you see the above code call is coming from the front layer to database layer.

Advantage

  • StackTrace provides detailed information about from where call came from the beginning till end. This is one reason developer can use StackTrace when there is a need to get, i.e., trace details level information.
  • Also StackTrace frame provides control on the caller method, provides assembly from where call is coming.

Disadvantage

  • Inline method does not get listed when code is compiled in Release mode, which gets listed when code is compiled in Debug mode.

To understand it, consider the below code changes in front layer code.

Now if you compile code in Debug mode with below configuration:

It will generate the below output for you, where you can see four lines, i.e., one extra line of calling to method "GetEmployeeList1".

So debug list all method calls, but now if you compile code in Release mode with below configuration:

It will generate below output for you, where you can see three lines. The line of calling method "GetEmployeeList1" is missing.

So StackTrace doesn't list out methods which are converted to inline method by compiler. if you want to list out, you can mark method as [MethodImpl(MethodImplOptions.NoInlining)].

If developer marks method as [MethodImpl(MethodImplOptions.AggressiveInlining)], then the method also does not get list in debug.

So StackTrace information can be spoof by making method inline.

  • As StackTrace provides every minute detail, StackTrace will show the full trace right into the core MS sourced assemblies, and will reveal details about what technologies you're using, and possible versions as well. This gives intruders valuable information on possible weaknesses that could be exploited.

    So always careful before displaying this information and put security on this.

Advantage Over Caller Information Attribute

  • It provides minute details which is not possible with Caller Information attribute.
  • Line number, Filename and Method Name information is given by StackFrame which cannot be changed by developer. But in case of Caller Information attribute developer can spoof by passing wrong value in caller information parameter.

Caller Information Attribute

This is a new feature introduced in C# 5.0. and attributes are part of System.Runtime.CompilerServices namespace. These attributes are required to be added as optional parameter in the method for which you need to get caller information.

Example

Accessibility ReturnType MethodName (Type parameterName,....,
                                    [CallerMemberName] string memberName = "",
                                    [CallerFilePath] string sourceFilePath = "",
                                    [CallerLineNumber] int sourceLineNumber = 0
Name Type Description
CallerMemberName string Provide caller method Name
CallerFilePath string Provide caller method File Name
CallerLineNumber int Provide caller Line number in File from where method gets called

Note

Caller of the method can also pass this value as this attribute is added as parameter to method.

Example when calling method which is decorated by caller information attribute:

To understand this, let's make a change in the DataLayer method like this:

//Data layer class for employee
 public string GetEmployeeList([CallerMemberName] string memberName = "",
                              [CallerFilePath] string fileName = "",
                             [CallerLineNumber] int lineNumber = 0)
 {

     return " Method Name: " + memberName + " File Name:" + fileName + " Line No: " + lineNumber;
 }

So running the above code provides the below output:

Advantage

  • Information of caller attribute cannot be spoofed till developer passes information in method parameter.
  • There is no runtime cost for this, i.e., it doesn't affect performance of the code as attribute are compile time.
  • It is very helpful to find out when call is coming from some unknown location like in case of "PropertyChange".

Disadvantage

  • Information of caller can be spoofed by developer if developer passes wrong information in the parameter of the caller information.
  • There is only one StackFrame, i.e., it will give information about who called method (immediate caller of method) but doesn't provide detailed information like StackTrace.
  • It's part of C# 5.0 so it's not working with older version of framework.

Advantage over StackTrace

  • As its complied time, there is no rutime cost like StackTrace (we need to create object of StackTrace runtime to get information).
  • Information provided by attribute cannot be spoofed by method attributes.

Do comment if the information is missing or wrong.

Referenced From

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

Pranay Rana
Software Developer (Senior) GMind Solusion
India India

Microsoft C# MVP (12-13)



Hey, I am Pranay Rana, working as a ITA in MNC. Web development in Asp.Net with C# and MS sql server are the experience tools that I have had for the past 5.5 years now.

For me def. of programming is : Programming is something that you do once and that get used by multiple for many years

You can visit my blog


StackOverFlow - http://stackoverflow.com/users/314488/pranay
My CV :- http://careers.stackoverflow.com/pranayamr

Awards:



You may also be interested in...

Pro

Comments and Discussions

 
-- There are no messages in this forum --
Permalink | Advertise | Privacy | Terms of Use | Mobile
Web02 | 2.8.170924.2 | Last Updated 13 Feb 2014
Article Copyright 2014 by Pranay Rana
Everything else Copyright © CodeProject, 1999-2017
Layout: fixed | fluid