Click here to Skip to main content
13,700,483 members
Click here to Skip to main content
Add your own
alternative version

Tagged as

Stats

6.7K views
198 downloads
16 bookmarked
Posted 26 Mar 2018
Licenced BSD

Memory Dump to outstream

, 4 Apr 2018
Rate this:
Please Sign up or sign in to vote.
Function and supporting class to write a memory dump with hex values and characters to an output stream

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 to send a memory dump to stream
class mem_dumper
{
public:
   //! Constructor
    /*! Construct object that can be serialised out to stream
        \param address start address of memory to serialise
        \param length number of bytes to serialise
     */
   mem_dumper(const void* address, size_t length)
   : address_(address), length_(length) 
   {}

private:
   // Address of data to dump
   const void* address_;
   // Number of bytes to dump
   size_t length_;

   // Give streaming operator access to streaming function
   friend std::ostream& operator<<(std::ostream& os, const mem_dumper& md);

   // Streaming function
   std::ostream& dump(std::ostream& os) const
   {
      // Save stream state
      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_)
      {
         // Address
         os << std::endl << std::setw(8) << (unsigned long)address_ + index;

         // Up to 16 bytes per line
         size_t width = (length_ - index) > 16 ? 16 : (length_ - index);
         
         // Hex codes
         for (size_t i = 0; i < 16; i++ )
         {
            // Gap after a 0 and 8 characters
            if( i % 8 == 0 )
               os << ' ';

            // Put in filler if we run out of bytes at the end
            if( i < width )
               os << ' ' << std::setw(2) << std::hex << (unsigned short)address[i+index];
            else 
               os << "   ";
         }
         os << ' ';

         // Printable characters
         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;
      }
      // Restore state
      os.copyfmt(state);
      return os;
   }
};

//! Stream operator for a mem_dumper
/*! Stream operator for a mem_dumper
    \param os output stream
    \param md mem_dumper object to serialise
    \return output stream
 */
std::ostream& operator<<(std::ostream& os, const mem_dumper& md)
{
    return md.dump(os);
}

//! Create a mem_dumper which can be serialised
/*! Create a mem_dumper which can be serialised
    \param address start address of memory to serialise
    \param length number of bytes to serialise
    \return mem_dumper object
 */
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

License

This article, along with any associated source code and files, is licensed under The BSD License

Share

About the Author

Orjan Westin
Software Developer (Senior)
United Kingdom United Kingdom
Orjan has worked as a professional developer - in Sweden and England - since 1993, using a wide range of languages (C++, Pascal, Delphi, C, C#, Visual Basic, PHP, Python and x86 assembler), but tends to return to C++.

You may also be interested in...

Comments and Discussions

 
Questiondownloaded zip misses some lines Pin
ehaerim30-Mar-18 4:02
memberehaerim30-Mar-18 4:02 
AnswerRe: downloaded zip misses some lines Pin
Orjan Westin4-Apr-18 2:15
professionalOrjan Westin4-Apr-18 2:15 
QuestionNice Job Pin
jeffie10029-Mar-18 4:25
memberjeffie10029-Mar-18 4:25 
QuestionVery clean Pin
John R. Shaw28-Mar-18 6:52
memberJohn R. Shaw28-Mar-18 6:52 
QuestionWhy address is not updated in every line? Pin
Cake Processor27-Mar-18 19:37
professionalCake Processor27-Mar-18 19:37 
AnswerRe: Why address is not updated in every line? Pin
Orjan Westin28-Mar-18 1:18
professionalOrjan Westin28-Mar-18 1:18 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

Permalink | Advertise | Privacy | Cookies | Terms of Use | Mobile
Web01-2016 | 2.8.180910.1 | Last Updated 4 Apr 2018
Article Copyright 2018 by Orjan Westin
Everything else Copyright © CodeProject, 1999-2018
Layout: fixed | fluid