콜스택 로그 남기기

Posted by 빵빵빵
2013/03/19 19:17 전산(컴퓨터)/PC-Windows



출처 : 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()

2013/03/19 19:17 2013/03/19 19:17

이 글에는 트랙백을 보낼 수 없습니다