Introduction
This is a simple piece of code which dumps a section of memory - with address, hex values, and characters - to a stream. I've written something like this a lot of times over the years, whenever I've needed a quick memory dump to log during debugging.
I wanted to make it easy to stream out, so I wrote this as a function which takes a memory address and number of bytes and returns an object with those parameters. This object's class has a function to dump the memory, and a befriended output operator that calls it, so the function can be called in a stream sequence.
Code
Since this is something I'd mostly use while debugging, I keep it all in a single header file, to make it easy to add when needed.
#include <iostream>
#include <iomanip>
class mem_dumper
{
public:
mem_dumper(const void* address, size_t length)
: address_(address), length_(length)
{}
private:
const void* address_;
size_t length_;
friend std::ostream& operator<<(std::ostream& os, const mem_dumper& md);
std::ostream& dump(std::ostream& os) const
{
std::ios state(NULL);
state.copyfmt(os);
os << std::hex << std::setfill('0');
size_t index = 0;
const unsigned char* address = static_cast<const unsigned char*>(address_);
while (index < length_)
{
os << std::endl << std::setw(8) << (unsigned long)address_ + index;
size_t width = (length_ - index) > 16 ? 16 : (length_ - index);
for (size_t i = 0; i < 16; i++ )
{
if( i % 8 == 0 )
os << ' ';
if( i < width )
os << ' ' << std::setw(2) << std::hex << (unsigned short)address[i+index];
else
os << " ";
}
os << ' ';
for( size_t i = 0; i < width; i++)
{
if( i % 8 == 0 )
os << ' ';
if( address[i+index] < 32 )
os << '.';
else
os << address[i+index];
}
index += 16;
}
os.copyfmt(state);
return os;
}
};
std::ostream& operator<<(std::ostream& os, const mem_dumper& md)
{
return md.dump(os);
}
inline mem_dumper mem_dump(const void* address, size_t length)
{
return mem_dumper(address, length);
}
Using the Code
To use it, simply pass in the address of the data and how many bytes you want to dump into the function, and send it to an output stream:
#include "mem_dump.hpp"
struct ExampleData
{
char text[22];
bool b;
int i;
ExampleData()
{
memcpy(text, "Blabla bla. Blah? Bla!", 22);
b = true;
i = 1234567;
}
} data;
std::cout << mem_dump(&data, sizeof(ExampleData)) << std::endl;
This will produce (address will vary, and the characters representing the int
bytes will vary depending on platform codepage):
0022FAC8 42 6c 61 62 6c 61 20 62 6c 61 2e 20 42 6c 61 68 Blabla b la. Blah
0022FAD8 3f 20 42 6c 61 21 01 cc 87 d6 12 00 ? Bla!.╠ çÍ.
History
- 26th March, 2018: Initial version
- 28th March, 2018: Fixed address printout increment issue in text and downloadable file