Notice: Any messages purporting to come from this site telling you that your password has expired, or that you need to "verify" your details, making threats, or asking for money, are
spam. We do not email users with any such messages. If you have lost your password you can obtain a new one by using the
password reset link.
Entire forum
➜ Programming
➜ STL
➜ Function tracer
It is now over 60 days since the last post. This thread is closed.
Refresh page
Posted by
| Nick Gammon
Australia (23,070 posts) Bio
Forum Administrator |
Date
| Sat 10 Jul 2004 05:51 AM (UTC) Amended on Sat 10 Jul 2004 06:07 AM (UTC) by Nick Gammon
|
Message
| 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:
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.
|
- Nick Gammon
www.gammon.com.au, www.mushclient.com | Top |
|
Posted by
| Nick Gammon
Australia (23,070 posts) Bio
Forum Administrator |
Date
| Reply #1 on Sat 10 Jul 2004 06:26 AM (UTC) |
Message
| A neat variation is to output to a stringstream, this could then be sent somewhere else (eg. written to a file, sent on the Internet, eaten by wild goats).
Here is an example, modifying the "main" function above:
#include <sstream>
int main (void)
{
ostringstream to; // trace output
trace::reset (&to); // direct to our string stream
trace t ("main");
f ();
f ();
f ();
trace::show_counts (); // output function counts
// show results (string in 'to')
cout << "trace output = " << endl << to.str ();
return 0;
}
Output
trace 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
3 f
6 g
1 main
|
- Nick Gammon
www.gammon.com.au, www.mushclient.com | Top |
|
The dates and times for posts above are shown in Universal Co-ordinated Time (UTC).
To show them in your local time you can join the forum, and then set the 'time correction' field in your profile to the number of hours difference between your location and UTC time.
10,320 views.
It is now over 60 days since the last post. This thread is closed.
Refresh page
top