Click here to Skip to main content
Click here to Skip to main content

Serialization of Memory Pointed by a Pointer

By , 8 Nov 2007
 

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:

void CArchive::WriteCount(DWORD_PTR dwCount);

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

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:

DWORD_PTR CArchive::ReadCount();

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

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

Using the code

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

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:

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:

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)

About the Author

shriram_gupta
Team Leader Canon India Pvt Ltd
India India
Member
Born and living in India, I'm an engineer in Computer Science & Engineering working in Canon India Pvt Ltd as a Module Leader responsible for coding, Team handling etc. I’m interested in leading a Project and working with C++, MFC, STL, COM and ATL.

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board.
Search this forum  
    Spacing  Noise  Layout  Per page   
GeneralAfxReadStringLength/AfxWriteStringLengthmemberdefrager10 Nov '07 - 7:02 
Hi,
 
Use ar.ReadCount and ar.WriteCount to save length of buffer.
AfxReadStringLength/AfxWriteStringLength are designed to serialize length of strings and not supported by vc6.
AnswerRe: AfxReadStringLength/AfxWriteStringLengthmembershriram_gupta10 Nov '07 - 16:05 
Hi,
 
Thank you for showing interest in my article. Smile | :)
 
I just concentrated to solve the problem. But I didn't pay attention to solve the problem in proper way. You let me to pay attention on it. Smile | :)
 
One short coming with CArchieve::ReadCount is that one can't do the schema checking, as I'm checking whether we are reading desirable data or not. In case of undesirable data, we are throwing CArchiveException::badSchema. Now this can’t be checked on using CArchieve::ReadCount.
 
By the way, WriteCount/ReadCount is good choice over AfxReadStringLenth/AfxWriteStringLenth. And the code can be modified as follows-
//AfxWriteStringLength(ar, nMax, 0);
ar.WriteCount(nMax);
And
/*
int nCharSize;
nMax = UINT(AfxReadStringLength(ar, nCharSize));
if (nCharSize != 1)
{
AfxThrowArchiveException(CArchiveException::badSchema);
return;
}
*/
nMax = UINT(ar.ReadCount());

 
Thanx
Ram

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

Permalink | Advertise | Privacy | Mobile
Web02 | 2.6.130523.1 | Last Updated 9 Nov 2007
Article Copyright 2007 by shriram_gupta
Everything else Copyright © CodeProject, 1999-2013
Terms of Use
Layout: fixed | fluid