출처 : http://www.codeproject.com/Articles/12949/A-Simple-C-Function-Call-Stack-Trace-Utility
<code>
// trace.hpp
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <stdarg.h>
#include <string>
#define CM_TRACE_FILE(trace_file) cm::Trace::LogToFile(trace_file)
#define CM_TRACE_FUNC(func_name) cm::Trace __CM_TRACE__(func_name, "()")
#define CM_TRACE_FUNC_ARG1(func_name, argfmt, arg) \
cm::Trace __CM_TRACE__(func_name, argfmt, arg)
#define CM_TRACE_FUNC_ARG2(func_name, argfmt, arg1, arg2) \
cm::Trace __CM_TRACE__(func_name, argfmt, arg1, arg2)
// more macros define....
namespace cm
{
class Trace
{
public:
explicit Trace(char *func_name, const char* argsfmt, ...)
{
char fmt[256] ={0};
sprintf(fmt, "%s%s", func_name, argsfmt);
va_list arglist;
va_start(arglist, argsfmt);
LogMsg(depth_, depth_ * 2, fmt, arglist);
va_end(arglist);
++depth_;
}
~Trace()
{
--depth_;
}
/// special the global log file.
void static LogToFile(const char *trace_file)
{
trace_file_ = trace_file;
}
private:
void LogMsg(int depth, int align, const char *fmt, va_list args)
{
FILE *fp = fopen(trace_file_.c_str(), "a+");
if (fp == NULL)
{
return;
}
time_t curTime;
time(&curTime);
char timeStamp[32] = { 0 };
strftime(timeStamp, sizeof(timeStamp),
"%Y%m%d.%H%M%S", localtime(&curTime));
// only log the timestamp when the time changes
unsigned int len = fprintf( fp, "%s %*.*s> (%d)",
(last_invoke_time_ != curTime) ?
timeStamp : " ",
2 * depth,
2 * depth,
nest_,
depth);
last_invoke_time_ = curTime;
len += vfprintf(fp, fmt, args);
len += fwrite("\n", 1, 1, fp);
fflush(fp);
fclose(fp);
}
private:
// the debug trace filename
static std::string trace_file_;
// function call stack depth
static int depth_;
static const char* nest_;
static time_t last_invoke_time_;
};
std::string Trace::trace_file_ = "";
int Trace::depth_ = 0;
// arbitrarily support nesting 34 deep for no particular reason
const char* Trace::nest_ =
"| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | ";
time_t Trace::last_invoke_time_ = 0;
} // end namespace cm
#endif // CM_TRACE_20060209_HPP
</code>
<code>
#include "cm/trace.hpp"
void foo()
{
CM_TRACE_FUNC("foo");
}
void bar(int x)
{
CM_TRACE_FUNC_ARG1("bar", "(%d)", x);
foo();
}
void foobar(int x, const char* s)
{
CM_TRACE_FUNC_ARG2("foobar", "(%d, %s)", x, s);
bar(789);
}
void foobar3(int x, int y, double z)
{
CM_TRACE_FUNC_ARG3("foobar3", "(%d, %d, %f)", x, y, z);
foobar(123, "4546");
}
int main()
{
CM_TRACE_FILE("./trace.log");
CM_TRACE_FUNC("main");
foo();
bar(23);
foobar(33, "char");
foobar3(12, 23, 34.45);
return 0;
}
</code>
20060211.132431 > (0)main()
| > (1)foo()
| > (1)bar(23)
| | > (2)foo()
| > (1)foobar(33, char)
| | > (2)bar(789)
| | | > (3)foo()
| > (1)foobar3(12, 23, 34.450000)
| | > (2)foobar(123, 4546)
| | | > (3)bar(789)
| | | | > (4)foo()