It is necessary to log memory dumps for certain memory areas, such as binary file read, data received on socket and so on.
The macro for memory dump (for purpose of logging completeness) is as follows:
#define DumpArray(Msg,Buf,Len,LogLevel) CLog::ArrayDump(Msg,Buf,Len,LogLevel,__FILE__,__FUNCTION__,__LINE__);
The declaration is as follows:
class CLog
{
private:
static CLogFile LogFile;
public:
static void LogInit(char* fileName);
static void LogMessage(char *msg, int logLevel, char *fileName, char *funcName, int lineNum);
static void LogMessageToFD(FILE *fd, char *msg, int logLevel, char *fileName, char *funcName, int lineNum);
static void ArrayDumpToFD(FILE *fd, char *msg, unsigned char *data, int len, LogLevel logLevel, char *fileName, char *funcName,
int lineNum);
static void ArrayDump(char *msg, unsigned char *data, int len, LogLevel logLevel, char *fileName, char *funcName, int lineNum);
};
Logging array dump uses similar format used by many popular debuggers, i.e. eight digits of offset (from start address), followed 16 bytes hex values, followed by 16 printable characters or dot '.'. Each 16, hex values and characters, are seperated by a space character after 8th entry for easier readability.
The code is as follows:
void CLog::ArrayDump(char *msg, unsigned char *data, int len, LogLevel logLevel, char *fileName, char *funcName, int lineNum) {
ArrayDumpToFD(LogFile.GetFD(), msg, data, len, logLevel, fileName, funcName, lineNum);
}
void CLog::ArrayDumpToFD(FILE *fd, char *msg, unsigned char *data, int len, LogLevel logLevel, char *fileName,
char *funcName, int lineNum) {
if(logLevel <= CLog::GlobalLogLevel) {
time_t tm_t=time(NULL);
tm t;
memcpy(&t, localtime(&tm_t), sizeof(tm));
fprintf(fd, "[%04d%02d%02d%02d%02d%02d][%s][%s][Memory Dump (size=%d): %s\n",
t.tm_year+1900, t.tm_mon+1, t.tm_mday, t.tm_hour, t.tm_min, t.tm_sec,
funcName, CLog::GetLogLevelStr(logLevel), len, msg);
int index=0;
while(data+index < data+len) {
//print offset
fprintf(fd, "%08d ", index);
//print hex
do{
if(index%8 == 0){
fprintf(fd, " ");
}
fprintf(fd, "%02X ",
(data+index
index++;
if(index%16 == 0 &&
data+index >= data+len) {
break;
}
}while(index%16 != 0);
index -= 16;
//print printable
fprintf(fd, " ");
do {
char ch='.';
if(data+index < data+len) {
if(isprint(*(data+index))) {
ch=*(data+index);
}
}
fprintf(fd, "%c", ch);
index++;
if(index %8 == 0) {
fprintf(fd, " ");
}
if(index%16 == 0 &&
data+index >= data+len) {
break;
}
}while(index%16 != 0);
fprintf(fd, "\n");
}
fprintf( fd, "]");
if(CLog::PrintFileNNum || logLevel == LogLevel::LogLevelError) {
fprintf(fd, "[%s,%d]", fileName, lineNum);
}
fprintf(fd, "\n");
}
}