ログの出力例
2023/03/02 22:07:10.900 PID:0x0000258c TID:0x00003214 あいうえお 2023/03/02 22:07:49.818 PID:0x0000258c TID:0x00003214 binary 00000000 f0 e0 d0 c0 b0 a0 00 01-02 03 04 05 06 07 08 09 ................ 00000010 80 70 60 50 40 .p`P@ 2023/03/02 22:07:49.819 PID:0x0000258c TID:0x00003214 かきくけこ
C ソース(Windows 用の型、関数、呼び出し規約を使用している)
#include <stdio.h> #include <Windows.h> // @func // 4 ビット文字変換 // 指定された値の 4 ビットを文字に変換して lpszBuffer へ出力 // @param // [I/O] lpszBuffer : 出力先 // [I/-] chValue : 文字に変換する値 void WINAPI ToHexChar(char* lpszBuffer, int chValue ) { chValue &= 0x0f; *lpszBuffer = chValue + (chValue < 0x0a ? '0' : 'a' - 0x0a); } // @func // ログ出力 // バイトポインタとそのバイト数を指定するとメモリダンプをメッセージと一緒に出力する // スレッドセーフではない // @param // [I/-] lpszPath : ログファイルのパス // [I/-] lpBytes : バイトポインタ。nBytes に 0 以下を指定した場合 NULL を指定可 // [I/-] nBytes : バイトポインタ先のメモリサイズ。0 を指定可能 // [I/-] lpszFormat : メッセージ書式 void WINAPIV DbgMsg(const char* const lpszPath, const char* lpBytes, int nBytes, const char* const lpszFormat, ...) { FILE* fp; if (fopen_s(&fp, lpszPath, "at") == NO_ERROR) { va_list va; // 0 10 20 30 40 50 60 70 69 // +---------+---------+---------+---------+---------+---------+---------+---------+ // 01234567890123456789012345678901234567890123456789012345678901234567890123456789 char szBuffer[] = { "\n" " 00000000 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................" }; int nBlankBytes = 0; const char* lpReadHex = lpBytes; DWORD nAddress = 0x00000000; SYSTEMTIME time; // 日時を取得 GetLocalTime(&time); va_start(va, lpszFormat); // 日時を出力 fprintf_s(fp, "%04d/%02d/%02d %02d:%02d:%02d.%03d PID:0x%08x TID:0x%08x ", time.wYear, time.wMonth, time.wDay, time.wHour, time.wMinute, time.wSecond, time.wMilliseconds, GetCurrentProcessId(), GetCurrentThreadId()); // メッセージを出力 vfprintf_s(fp, lpszFormat, va); while (nBytes > 0x00) { char* lpHex = &szBuffer[15]; char* lpChar = &szBuffer[64]; int i; int nRemainBytes = nBytes; if (nRemainBytes > 0x10) { nRemainBytes = 0x10; } nBytes -= nRemainBytes; nBlankBytes = 0x10 - nRemainBytes; ToHexChar(&szBuffer[0x05], (nAddress >> 0x1c) & 0x0f); ToHexChar(&szBuffer[0x06], (nAddress >> 0x18) & 0x0f); ToHexChar(&szBuffer[0x07], (nAddress >> 0x14) & 0x0f); ToHexChar(&szBuffer[0x08], (nAddress >> 0x10) & 0x0f); ToHexChar(&szBuffer[0x09], (nAddress >> 0x0c) & 0x0f); ToHexChar(&szBuffer[0x0a], (nAddress >> 0x08) & 0x0f); ToHexChar(&szBuffer[0x0b], (nAddress >> 0x04) & 0x0f); ToHexChar(&szBuffer[0x0c], (nAddress >> 0x00) & 0x0f); nAddress += 0x10; // データを出力 for (i = 0; i < nRemainBytes; i++) { // データを CHAR で出力 char ch = isprint((unsigned char)*lpReadHex) ? *lpReadHex : '.'; *lpChar = ch; lpChar++; // データを HEX で出力 ToHexChar(&lpHex[0], ((unsigned char)*lpReadHex >> 0x04) & 0x0f); ToHexChar(&lpHex[1], ((unsigned char)*lpReadHex >> 0x00) & 0x0f); lpHex += 3; lpReadHex++; } // 16 バイトに満たないとき、ブランクを出力 if (nBlankBytes > 0) { for (i = 0; i < nBlankBytes; i++) { // データを CHAR(ブランク)で出力 *lpChar = ' '; lpChar++; // データを HEX(ブランク)で出力 lpHex[0] = ' '; lpHex[1] = ' '; lpHex += 3; } if (nBlankBytes > 0x08) { szBuffer[38] = ' '; } } fprintf_s(fp, szBuffer); } fprintf_s(fp, "\n"); fclose(fp); va_end(va); } } int main(int argc, char* argv[]) { char stream[] = { 0xf0, 0xe0, 0xd0, 0xc0, 0xb0, 0xa0, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x80, 0x70, 0x60, 0x50, 0x40, }; DbgMsg(".\\testLog.log", NULL, 0, "あいうえお"); DbgMsg(".\\testLog.log", stream, sizeof(stream), "binary"); DbgMsg(".\\testLog.log", NULL, 0, "かきくけこ"); return 0; }