Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Function Calling Sequence Tracer Class

0.00/5 (No votes)
15 Aug 2003 1  
A class to trace the sequence at which functions are called.

Sample image

Introduction

Sometimes in complex applications large number of messages are to be processed and there are a large number of functions for handling requests and events. Sometimes it is confusing to see what are the functions called by a given function. What are the functions that will lead to a call to a particular function. What is the sequence of calling of all these functions. If some programmer is supposed to continue an unfinished work of another programmer, in a badly documented system it will be a nightmare. Even the same programmer who had previously made all this can be confused. I experienced this problem in one of my projects. I searched for a solution on the Internet but I was unlucky, so I started to do it myself. I wrote a class to trace methods in the application and log all the sequence to a file in a readable format.

The idea

The idea of my solution is to use a global object of a small class having some static member functions and static member variables. In an early point in the application (in the constructor of the application class, for example) we specify the file that will hold the sequence log. This is done using a static function. The class contains some private static member variables to maintain the current level of the call. At the beginning of a function an instance of this class is instantiated in the stack using the constructor, which takes as a parameter the text that should be logged. At the end of the function, this class instance will be out of scope so the destructor of the class will be called and the level will decrease.

Implementation

The following is the header file of the SequenceTracer class:

// SequenceTracer.h


#ifndef _SEQUENCE_TRACER
#define _SEQUENCE_TRACER

#include <fstream>  // for std::ofstream



class SequenceTracer  
{
public:
    static void Start(const char * fileName); // Set the file name and start

    SequenceTracer(const char * text); // The only constructor

    virtual ~SequenceTracer();
protected:
    static int Stack[256]; // The stack maintaing sequence numbers

    static int Level; // The current level in the stack

    static std::ofstream * OutStream; // The always open output stream


};

#endif //_SEQUENCE_TRACER

And this is the implementation file for the class:

// SequenceTracer.cpp


#include "SequenceTracer.h"

//////////////////////////////////////////////////////////////////////

int SequenceTracer::Level;
std::ofstream * SequenceTracer::OutStream;
int SequenceTracer::Stack[256];
//////////////////////////////////////////////////////////////////////

void SequenceTracer::Start(const char *fileName)
{
    OutStream = new std::ofstream (fileName);
}
//////////////////////////////////////////////////////////////////////

SequenceTracer::SequenceTracer(const char * text)
{
    if (!OutStream) // Outstream should be initialized

        return;

    for (int i = 0; i < Level; i++)
        *OutStream << '\t'; // Make indentation


    Stack[Level]++; // Increment the sequence number


    for (i = 0; i < Level, Stack[i] > 0; i++)
        *OutStream << Stack[i] << '.'; // Print the sequence number


    *OutStream << " "; // Add a space

    *OutStream << text << "\n"; // Write the text followed by newline

    Level++; // Increase the level

}
//////////////////////////////////////////////////////////////////////

SequenceTracer::~SequenceTracer()
{
    Stack[Level] = 0; // Reset the sequence number

    Level--; // Decrease the level

    if (Level < 0) // If we are finished

    {
        delete OutStream; // Write to the file and delete stream

        OutStream = 0; // Reset the stream pointer

    }
}
//////////////////////////////////////////////////////////////////////

Using the class

Using this class is very easy simply in three steps:

  1. Include the SequencTracer.h in CPP files in which you want to trace function sequence
  2. In an early point in the application (The application constructor for example) call the static function Start and give this function the name of the file to be created and will store all the sequence
  3. In the beginning of any function you would like to figure out the usage, instantiate an object of the class in the stack

After you run the application and the level is less than 0, you can see the contents of the sequence file. It will look like:

Sample image

I made an application specially to test the class. I made two helper macros to further simplify using the class:

#ifdef _DEBUG
#define SEQ_TRACE(txt) SequenceTracer unique_variable_name##__LINE__ (txt)
#define SEQ_START(fileName) SequenceTracer::Start(fileName)
#else
#define  SEQ_TRACE(txt)
#define SEQ_START(fileName)
#endif
// Thanks to Michael Dunn for ##__LINE__

History

  • 16-8-2003: Article submitted, minor updates.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here