适用于无法对code Debug。函数间的调用执行关系只能通过查看源代码,无法确定运行的程序是否走到相应的函数。利用C++的RAII机制,进入函数和离开函数自动记录一次Log,输出文件查看程序执行流程。
part code:
#define LOG_FUNCTION(filename, funcname, lines) \
CLogFunction logFunctionName(filename, funcname, lines)
#define MAX_STR_LEN 1024
void __stdcall write_log(char* lpszFmt, ...)
{
FILE* f = fopen("shell.log", "at");
if(f)
{
va_list args;
va_start(args, lpszFmt);
char cBuffer[MAX_STR_LEN];
memset(cBuffer,0,MAX_STR_LEN);
_vsnprintf( cBuffer, MAX_STR_LEN-1, lpszFmt, args);
fwrite(cBuffer,strlen(cBuffer),1,f);
fclose(f);
}
}
class CLogFunction
{
public:
CLogFunction(char *szFileName, char *szFunctionName, UINT32 uLine)
{
LOG_FUNCTION(__FILE__, __FUNCTION__, __LINE__);
m_pFileName = szFileName;
m_pFunctionName = szFunctionName;
m_nid = InterlockedIncrement(&nID);
write_log( "ThreadID:%d +[S:%d]EnterFunc:%s +Line:%d",
GetCurrentThreadId(),
m_pFunctionName,
uLine);
}
~CLogFunction()
{
LOG_FUNCTION(__FILE__, __FUNCTION__, __LINE__);
write_log( "ThreadID:%d +[E:%d]LeaveFunc:%s ",
GetCurrentThreadId(),
m_pFunctionName);
}
private:
char *m_pFileName;
char *m_pFunctionName;
long m_nid;
};
然后在每个函数的入口添加代码,如:
int main(int argc, char *argv[])
{
LOG_FUNCTION(__FILE__, __FUNCTION__, __LINE__);
简单记录部分Function,具体实现用到多线程,自动为工程中函数添加LOG_FUNCTION()以及对生成log文件的分析工具。。。。。
***************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************
简单log记录输出:
// stdafx.cpp : 只包括标准包含文件的源文件
// SuiteCommand.pch 将作为预编译头
// stdafx.obj 将包含预编译类型信息
#include "stdafx.h"
CFile g_hFile;
BOOL is_open = FALSE;
void DLL_LOG_W(__in LPCWSTR lpOutputString)
{
OutputDebugStringW(lpOutputString);
}
void DLL_LOG_A(__in LPCSTR lpOutputString)
{
OutputDebugStringA(lpOutputString);
}
HINSTANCE GetCurDllInstance()
{
HINSTANCE hInstance = NULL;
MEMORY_BASIC_INFORMATION mbi = {0};
do
{
if (0 == VirtualQuery((void*)(&GetCurDllInstance), &mbi, sizeof(mbi)))
{
break;
}
//BaseAddress具体某页的基指,而AllocationBase则是连续N页的基指,AllocationBase就是instance
hInstance = reinterpret_cast<HINSTANCE>(mbi.AllocationBase);
} while (FALSE);
ASSERT(NULL != hInstance);
return hInstance;
}
CString GetCurDllDir()
{
TCHAR szFileName[1024] = {0};
CString strDir;
if (0 != GetModuleFileName(GetCurDllInstance(), szFileName, _countof(szFileName)))
{
strDir = szFileName;
int nIndex = strDir.ReverseFind(_T('\\'));
strDir = strDir.Left(nIndex);
}
ASSERT(!strDir.IsEmpty());
return strDir;
}
void initlog()
{
CString path = GetCurDllDir();
CString timestr;
CreateDirectory(path + _T("\\log"),NULL);
path +=_T("\\log\\debug.log");
is_open = g_hFile.Open(path, CFile::modeCreate | CFile::modeWrite|CFile::modeNoTruncate | CFile::shareDenyWrite);
if (is_open == FALSE)
{
path = GetCurDllDir();
path +=_T("\\debug.log");
is_open = g_hFile.Open(path, CFile::modeCreate | CFile::modeWrite|CFile::modeNoTruncate | CFile::shareDenyWrite);
return;
}
ULONGLONG len = g_hFile.GetLength();
if (len>(1024*1024))
{
g_hFile.Close();
g_hFile.Remove(path);
g_hFile.Open(path, CFile::modeCreate | CFile::modeWrite|CFile::modeNoTruncate | CFile::shareDenyWrite);
}
}
void closelog()
{
if (is_open)
{
g_hFile.Close();
is_open = FALSE;
}
}
void logoutput(CStringA logs)
{
if (is_open)
{
/* CTime tm;
tm=CTime::GetCurrentTime(); */
SYSTEMTIME st;
CStringA strDate,strTime;
GetLocalTime(&st);
strDate.Format("%04d/%02d/%02d",st.wYear,st.wMonth,st.wDay);
strTime.Format("%02d:%02d:%02d",st.wHour,st.wMinute,st.wSecond);
g_hFile.SeekToEnd();
CStringA temp = "LOGOUT ";
g_hFile.Write(temp,temp.GetLength());
g_hFile.Write(strDate,strDate.GetLength());
g_hFile.Write("--",2);
g_hFile.Write(strTime,strTime.GetLength());
g_hFile.Write(":",1);
g_hFile.Write(logs,logs.GetLength());
g_hFile.Write("\r\n",(UINT)strlen("\r\n"));
}
}
BOOL CheckisUnicode(WCHAR* str)
{
int len = wcslen(str);
WCHAR* ptr = str;
for(int i = 0;i<len;i++)
{
WCHAR code = ptr[i];
code = code&0xFF00;
if (code)
{
return TRUE;
}
}
return FALSE;
}
// stdafx.h : 标准系统包含文件的包含文件,
// 或是经常使用但不常更改的
// 特定于项目的包含文件
#pragma once
void DLL_LOG_W(__in LPCWSTR lpOutputString);
void DLL_LOG_A(__in LPCSTR lpOutputString);
void logoutput(CStringA logs);
void initlog();
void closelog();
BOOL CheckisUnicode(WCHAR* str);