Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / desktop / MFC

Serialization of Memory Pointed by a Pointer

2.78/5 (3 votes)
8 Nov 2007CPOL1 min read 1   448  
This article is a demonstration of serialization of dynamically allocated memory which is neither a derived class of CObject nor a CString. I.e., a kind of Variable or Object Persistence in MFC even if the object is a non-CObject derived class object.

Introduction

Some times we need to save memory pointed by the pointer variable rather than the pointer variable itself, i.e., memory allocated on heap. For example, when we create an object (which is not derived from CObject) on the heap and we want to serialize the object, or we allocate some memory either using C / C++ memory allocation routines (malloc, calloc, or new) or Windows API functions (GlobalAlloc, HeapAlloc, VirtualAlloc etc.).

The MFC serialization architecture doesn't provide any explicit mechanism to save memory pointed by a pointer variable of an object of a class which is not derived from CObject. If the pointer is an object of a class which is derived from CObject or CString, it can be serialized. But if it is a char *, can it be serialized? Most probably, it can't be. That is why I present this article to solve the problem. This article is for adding serialization to non-CObject derived classes, i.e., Object Persistence in MFC even for non-CObject derived class objects.

Background

The basic ideas behind this is that you will first need to save the size of memory by using the following function:

C++
void CArchive::WriteCount(DWORD_PTR dwCount);

Now, let's save the memory pointed by the pointer variable by using the following function:

C++
void CArchive::Write(const void* lpBuf, UINT nMax);

Now, in the case of restoring back, you will first need to read the size of memory pointed by the pointer variable by using the following function:

C++
DWORD_PTR CArchive::ReadCount();

Then you will need to read the memory content by using the following function:

C++
UINT CArchive::Read(void* lpBuf, UINT nMax);

Using the code

Using the above basic ideas, you can make the following two utility functions:

C++
void WritePointer(CArchive& ar, const void* lpBuf, UINT nMax);
void ReadPointer(CArchive& ar, void*& lpBuf, UINT& nMax);

Implementation of the above functions is given below:

C++
void WritePointer(CArchive& ar, const void* lpBuf, UINT nMax)
{
    ar.WriteCount(nMax);
    ar.Write(lpBuf, nMax);
}

void ReadPointer(CArchive& ar, void*& lpBuf, UINT& nMax)
{
    ASSERT(lpBuf == NULL);

    nMax = UINT(ar.ReadCount());
    lpBuf = malloc(nMax);
    UINT nBytesRead = ar.Read(lpBuf, nMax);
    if (nBytesRead != nMax)
    {
        AfxThrowArchiveException(CArchiveException::endOfFile);
    }
}

Let's now use the above functions:

C++
CPointerSerializationDoc::CPointerSerializationDoc(): m_buf(NULL)
{
    wchar_t String[] = _T("This is the initialized value in m_buf.");
    UINT nMax = sizeof(String);
    m_buf = malloc(nMax);
    memcpy_s(m_buf, nMax, String, nMax);
}

void CPointerSerializationDoc::Serialize(CArchive& ar)
{
    if (ar.IsStoring())
    {
        // Let's store the actual content pointed by m_buf pointer;
        
        // Following is wrong, because this will store the pointer value, 
        // but not the actual content pointed by the pointer.
        // ar<<m_buf;

        // So use the following function;
        WritePointer(ar, m_buf, nMaxCount);
        //nMaxCount - size of memory content;
    }
    else
    {
        // Let's load the actual content pointed by m_buf pointer;

        // Following is wrong, because pointer value will be loaded but not 
        // the actual content pointed by the pointer.
        // ar>>m_buf;

        // So use the following function;
        UINT nMaxCount = 0;
        ReadPointer(ar, m_buf, nMaxCount);
    }
}

History

  • Nov. 8, 2007 - Article created.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)