The code below is for a simple function tracer. The idea is to output debugging information to somewhere (eg. standard output) to show when a function has been called. The constructor supplies the function name and echoes "begin name" to the output stream. The destruction echoes "--end name" when the function terminates.
It also uses a map of function names so that it can count how many times a function was called. You could use this for some simple profiling.
To use it, just include the class in your project, and then put something like:
at the start of your functions. This will then echo "begin func_name" when that line is reached.
It is important to give the class variable a name (like "x" in the example). Without it, like this:
the compiler will construct a temporary object which will immediately be destroyed, thus showing the "--end func_name" message at the wrong time.
You can use any standard ostream as the recipient of the trace messages (eg. cout, cerr). For no tracing (eg. in production) use 0 as the output stream.
You can turn tracing on and off with the "reset" member function. eg.
To show the summaries of counts just call:
Output
The output shows the call sequence (eg. main calls f which calls g).
The summary at the end shows the count of each function call.
It also uses a map of function names so that it can count how many times a function was called. You could use this for some simple profiling.
To use it, just include the class in your project, and then put something like:
trace x ("func_name");
at the start of your functions. This will then echo "begin func_name" when that line is reached.
It is important to give the class variable a name (like "x" in the example). Without it, like this:
trace ("func_name"); // don't do this!
the compiler will construct a temporary object which will immediately be destroyed, thus showing the "--end func_name" message at the wrong time.
You can use any standard ostream as the recipient of the trace messages (eg. cout, cerr). For no tracing (eg. in production) use 0 as the output stream.
You can turn tracing on and off with the "reset" member function. eg.
trace::reset (0); // turn tracing off
trace::reset (&cout); // turn tracing on, output to cout
To show the summaries of counts just call:
trace::show_counts ();
#ifdef WIN32
#pragma warning( disable : 4786)
#endif
#include <iostream>
#include <map>
#include <string>
using namespace std;
class trace
{
const string name;
const int which;
static ostream * os;
static map<string, int> invoc_count;
public:
// constructor shows beginning of function
trace (const string & s)
: name (s), which (++invoc_count [s])
{
if (os)
*os << "begin " << name << " #" << which << endl;
}
// destructor shows end of function
~trace ()
{
if (os)
*os << "--end " << name << " #" << which << endl;
}
// change output stream to something else (eg. &cout, or 0)
static void reset (ostream * o)
{
os = o;
}
// show counts of how many times every function called
static void show_counts ()
{
if (os)
for (map<string, int>::const_iterator i = invoc_count.begin ();
i != invoc_count.end ();
i++)
*os << i->second << " " << i->first << endl;
}
// reset all counts
static void reset_counts ()
{
invoc_count.clear ();
}
}; // end of trace
// initialise static variables
ostream * trace::os = &cout;
map<string, int> trace::invoc_count;
void g ()
{
trace t ("g");
}
void f ()
{
trace t ("f");
g ();
g ();
}
int main (void)
{
trace t ("main");
f ();
f ();
f ();
trace::reset (0);
{
trace t ("foo");
}
trace::reset (&cout);
{
trace t ("bah");
}
trace::show_counts ();
return 0;
}
Output
begin main #1
begin f #1
begin g #1
--end g #1
begin g #2
--end g #2
--end f #1
begin f #2
begin g #3
--end g #3
begin g #4
--end g #4
--end f #2
begin f #3
begin g #5
--end g #5
begin g #6
--end g #6
--end f #3
begin bah #1
--end bah #1
1 bah
3 f
1 foo
6 g
1 main
--end main #1
The output shows the call sequence (eg. main calls f which calls g).
The summary at the end shows the count of each function call.