//============================================================================== // Brief : アサート // Return : void : なし // Arg : TCHAR *pExp : 判定条件式文字列 // Arg : TCHAR *pFileName : ファイル名 // Arg : int *nLine : 行番号 // Arg : TCHAR *pFormat : 表示メッセージフォーマット //============================================================================== void DebugAssert( TCHAR *pExp, TCHAR *pFileName, int nLine, TCHAR *pFormat, ... ) { TCHAR aStr[ DEBUG_OUTPUT_STRING_LEN ]; // 表示文字列 va_list args; // 引数 // 表示文字列作成 va_start( args, pFormat ); _vsntprintf_s( &aStr[ 0 ], DEBUG_OUTPUT_STRING_LEN, _TRUNCATE, pFormat, args ); va_end( args ); // エラーメッセージ出力 PrintMessageToMessageBox( _T( "*****ASSERT*****\n%sの%d行目\n%s\n%s\n" ), pFileName, nLine, pExp, &aStr[ 0 ] ); PrintMessageToDebugWindow( _T( "\n*****ASSERT*****\n%sの%d行目\n%s\n%s\n\n" ), pFileName, nLine, pExp, &aStr[ 0 ] ); // 終了 if( !g_bWindowModeDebug ) { // フルスクリーンモードのときはブレークしない abort( ); } if( MessageBox( g_hWndDebug, _T( "デバッグを終了しますか?\n" ), _T( "確認" ), MB_YESNO ) == IDYES ) { abort( ); } }
// 记录日志 int CLogMgr::LogEventArgs(int nLevel, LPCTSTR lpFormat, va_list argp) { const int nBufLen = MAX_PATH * 2; TCHAR szBuf[nBufLen]; int nStrLen=_vsntprintf_s(szBuf, nBufLen-1, lpFormat, argp); if(nStrLen>0) szBuf[nStrLen] = 0; FILE* lpFile = _tfopen(m_strLogFile, _T("a+")); if ( lpFile != NULL ) { // 获取文件大小 int nResult = -1; struct _stat FileBuff; nResult = T_STAT(m_strLogFile, &FileBuff); if (0 != nResult) { return -1; // 获取文件大小失败 } long lSize = FileBuff.st_size; // 文件大于设定大小需要进行转储,默认最大1MB if (lSize > m_nMaxLogFileSize) { fclose(lpFile); // 进行日志文件转储,转储时保证只保存指定个数的备份文件 FileReName(m_strLogFile, m_strLogFileName + _T(".") + LOG_CONVEY_FILE_NAME); // 删除多余文件(规矩通配符规则和时间顺序删除,保留最新的若干文件) FileConveySave(m_strLogPath, m_strLogFileName + _T(".") + LOG_CONVEY_RULE, m_nMaxLogFileNumber); // 删除备份文件 //_tunlink(m_strLogFile + _T(".bak")); // 重命名文件名为备份文件名 //_trename(m_strLogFile, m_strLogFile + _T(".bak")); // 打开新文件 lpFile = _tfopen(m_strLogFile, _T("w+"));//,ccs=UTF-8")); if (lpFile == NULL) { return -2; // 打开可写的新文件失败 } } SYSTEMTIME st; GetLocalTime(&st); CString strLevel; if (nLevel == LOG_LEVEL_DEBUG) { strLevel = __DEBUG; } else if (nLevel == LOG_LEVEL_INFO) { strLevel = __INFO; } else if (nLevel == LOG_LEVEL_ERROR) { strLevel = __ERROR; } else if (nLevel == LOG_LEVEL_CRITICAL) { strLevel = __CRITICAL; } else { strLevel = __DEBUG; } LPCTSTR lpStr = _tcschr(lpFormat, _T('\n')); if ( lpStr != NULL ) { lpStr = _T("%s %02d-%02d-%02d %02d:%02d:%02d[%u] : %s"); } else { lpStr = _T("%s %02d-%02d-%02d %02d:%02d:%02d[%u] : %s\n"); } DWORD dwCurThreadID = GetCurrentThreadId(); _ftprintf(lpFile, lpStr, strLevel, st.wYear, st.wMonth, st.wDay, st.wHour, st.wMinute, st.wSecond, dwCurThreadID, szBuf); fclose(lpFile); } return 0; }
void cLogLight::Add(const DWORD error,const TCHAR* Format, ...) { PTCHAR Mess(NULL); try { va_list args; va_start( args, Format ); // Init the user arguments list. unsigned int i=1; unsigned mult=1; int result; for(Mess=new TCHAR[MSG_BUF_SIZE]; (result=_vsntprintf_s( Mess, MSG_BUF_SIZE*mult,_TRUNCATE, Format, args ))<0 && i<MSG_BUF_SIZE_DOUBLING; i++, mult <<= 1) { delete [] Mess; Mess = NULL; Mess=new TCHAR[MSG_BUF_SIZE * (mult << 1)]; } tstring winError; if (result<0) { TCHAR truncated[]=_T("MESSAGE TRUNCATED"); _tcscpy_s(Mess+MSG_BUF_SIZE*mult-_countof(truncated)-1,_countof(truncated),truncated); } else { if(error!=ERROR_SUCCESS) { LPVOID lpBuffer; if(FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_FROM_SYSTEM, NULL, error, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR) &lpBuffer, 16, NULL) != 0) { winError+=_T(". (0x")+i2tstring(error,16)+_T(") ")+reinterpret_cast<PTCHAR>(lpBuffer); LocalFree(lpBuffer); } else { winError+=_T(". Unknown WinError code ")+i2tstring(error,16); } } } AddList(Mess+winError); delete [] Mess; Mess = NULL; } catch(...) { try { if (Mess) delete [] Mess; //Preventing memory leaks AddList(_T("cLog::Add: Exception happened")); } catch(...) { //One more exception happened //going further } } }
//--------------------------------------------------------------------------------------------------------------// void CTracer::TraceMessage(MessageTypeEnum Type, LPCTSTR szSource, LPCTSTR pszMessage, ...) { TCHAR szDate[64]; if (0 == ::GetDateFormat( LOCALE_USER_DEFAULT, DATE_SHORTDATE, NULL, NULL, szDate, sizeof(szDate)/sizeof(TCHAR))) { szDate[0] = _T('?'); szDate[1] = _T('\0'); } TCHAR szTime[32]; if (0 == ::GetTimeFormat( LOCALE_USER_DEFAULT, LOCALE_NOUSEROVERRIDE, NULL, NULL, szTime, sizeof(szTime)/sizeof(TCHAR))) { szTime[0] = _T('?'); szTime[1] = _T('\0'); } TCHAR cType; switch (Type) { case enMtInformation: cType = _T('I'); break; case enMtWarning: cType = _T('W'); break; case enMtError: cType = _T('E'); break; default: cType = _T('?'); } va_list arglist; va_start(arglist, pszMessage); TCHAR szMessage[4096]; _vsntprintf_s(szMessage,sizeof(szMessage), 4096, pszMessage, arglist); TCHAR szOutputLine[4096]; ::wsprintf( szOutputLine, _T("[%#04X] %s %s %c %s %s"), ::GetCurrentThreadId(), szDate, szTime, cType, szMessage, szSource!=NULL?szSource:_T("")); if (m_Destination & enMdWindow) { HWND hWnd = GetWindowHandle(); sMessage Msg; Msg.szMessage = szMessage; Msg.szSource = szSource; if (hWnd) ::SendMessage(hWnd, GetMessageId(), Type, reinterpret_cast<LPARAM>(&Msg)); } ::lstrcat(szOutputLine, _T("\n")); if (m_Destination & enMdDebug) ::OutputDebugString(szOutputLine); if (m_Destination & enMdFile) WriteMessageToFile(szOutputLine); }
/** dropt_vsnprintf * * vsnprintf wrapper to provide ISO C99-compliant behavior. * * PARAMETERS: * OUT s : The destination buffer. May be NULL if n is 0. * If non-NULL, always NUL-terminated. * IN n : The size of the destination buffer, measured in * dropt_char-s. * IN format : printf-style format specifier. Must not be NULL. * IN args : Arguments to insert into the formatted string. * * RETURNS: * The number of characters that would be written to the destination * buffer if it's sufficiently large, excluding the NUL-terminator. * Returns -1 on error. */ int dropt_vsnprintf(dropt_char * s, size_t n, const dropt_char * format, va_list args) { #if __STDC_VERSION__ >= 199901L || __GNUC__ /* ISO C99-compliant. * * As far as I can tell, gcc's implementation of vsnprintf has always * matched the behavior required by the C99 standard (which is to * return the necessary buffer size). * * Note that this won't work with wchar_t because there is no true, * standard wchar_t equivalent of snprintf. swprintf comes close but * doesn't return the necessary buffer size (and the standard does not * provide a guaranteed way to test if truncation occurred), and its * format string can't be used interchangeably with snprintf. * * It's simpler not to support wchar_t on non-Windows platforms. */ assert(format != NULL); return vsnprintf(s, n, format, args); #elif defined __BORLANDC__ /* Borland's compiler neglects to NUL-terminate. */ int ret; assert(format != NULL); ret = vsnprintf(s, n, format, args); if (n != 0) { s[n - 1] = DROPT_TEXT_LITERAL('\0'); } return ret; #elif defined _MSC_VER /* _vsntprintf and _vsnprintf_s on Windows don't have C99 semantics; * they return -1 if truncation occurs. */ va_list argsCopy; int ret; assert(format != NULL); va_copy(argsCopy, args); ret = _vsctprintf(format, argsCopy); va_end(argsCopy); if (n != 0) { assert(s != NULL); #if _MSC_VER >= 1400 (void) _vsntprintf_s(s, n, _TRUNCATE, format, args); #else /* This version doesn't necessarily NUL-terminate. Sigh. */ (void) _vsnprintf(s, n, format, args); s[n - 1] = DROPT_TEXT_LITERAL('\0'); #endif } return ret; #else #error Unsupported platform. dropt_vsnprintf unimplemented. return -1; #endif }