Memory Allocation Example
An object may need to pass memory between it and the client at some point in the object's lifetime—this applies to in-process as well as out-of-process servers. When such a situation arises the object must use the task allocator as described in Chapter 2. That is, the object must allocate memory whose ownership is transferred from one party to another through an interface function by using the local task allocator.
CoGetMalloc provides a convenient way for objects to allocate working memory as well. For example, when the TextRender object (see Chapter 3, "Designing and Implementing Objects") under consideration in this document loads text from a file in the function IPersistFile::Load (that is, CTextRender::Load) it will want to make a memory copy of that text. It would use the task allocator for this purpose as illustrated in the following code (unnecessary details of opening files and reading data are omitted for simplicity):
//Implementation of IPersistFile::Load
HRESULT CTextRender::Load (char *pszFile, DWORD grfMode) {
...int hFile;
...DWORD cch;
...IMalloc * pIMalloc;
...HRESULT hr;
.../*
... * Open the file and seek to the end to set the
... * cch variable to the length of the file.
... */
...hr=CoGetMalloc(MEMCTX_TASK, &pIMalloc);
...if (FAILED(hr))
......//Close file and return failure
...psz=pIMalloc->Alloc(cch);
...pIMalloc->Release();
...if (NULL==psz)
......//Close file and return failure
...//Read text into psz buffer and close file
...
...//Save memory pointer and return success
...m_pszText=psz;
...return NOERROR;
...}
If an object will make many allocations throughout its lifetime, it makes sense to call CoGetMalloc once when the object is created, store the IMalloc pointer in the object (m_pIMalloc or such), and call IMalloc::Release when the object is destroyed. Alternatively, the APIs CoTaskMemAlloc and its friends may be used.