65.9K
CodeProject 正在变化。 阅读更多。
Home

序列化指针指向的内存

starIconstarIcon
emptyStarIcon
starIcon
emptyStarIconemptyStarIcon

2.78/5 (3投票s)

2007年11月9日

CPOL

1分钟阅读

viewsIcon

33771

downloadIcon

461

本文演示了对动态分配的内存进行序列化,该内存既不是 CObject 的派生类,也不是 CString。 也就是说,即使对象不是 CObject 派生类对象,也可以在 MFC 中实现变量或对象的持久化。

引言

有时我们需要保存指针变量指向的内存,而不是指针变量本身,即堆上分配的内存。 例如,当我们创建一个(不是从 CObject 派生的)堆对象并希望序列化该对象时,**或者**我们使用 C / C++ 内存分配例程(malloccallocnew)或 Windows API 函数(GlobalAllocHeapAllocVirtualAlloc 等)分配一些内存。

MFC 序列化架构没有提供任何显式机制来保存由非 CObject 派生类的对象指针变量指向的内存。 如果指针是 CObjectCString 派生类的对象,则可以对其进行序列化。 但是,如果它是 char *,可以对其进行序列化吗? 很可能不行。 这就是我撰写本文的原因,以解决这个问题。 本文旨在为非 CObject 派生类添加序列化,即即使对于非 CObject 派生类对象,也能在 MFC 中实现对象持久化。

背景

其基本思想是,首先需要使用以下函数保存内存大小

void CArchive::WriteCount(DWORD_PTR dwCount);

现在,让我们使用以下函数保存指针变量指向的内存

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

现在,在恢复的情况下,首先需要使用以下函数读取指针变量指向的内存大小

DWORD_PTR CArchive::ReadCount();

然后您需要使用以下函数读取内存内容

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

使用代码

使用上述基本思想,您可以创建以下两个实用函数

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

上述函数的实现如下

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);
    }
}

现在让我们使用上述函数

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);
    }
}

历史

  • 2007 年 11 月 8 日 - 创建文章。
© . All rights reserved.