使用IMalloc接口来分配内存演示程序

使用IMalloc接口来分配内存演示程序

 

借助一个Win32程序展示了如何利用OLE的IMalloc接口来分配任务类型和共享类型的内存。

 

程序运行画面如下:

 

源码MALLOC.H:

  1. #ifndef _MALLOC_H_
  2. #define _MALLOC_H_
  3. LRESULT PASCAL MallocWndProc(HWNDUINTWPARAMLPARAM);
  4. #define CALLOCS 10
  5. /*
  6.  * Application defined classes and types.
  7.  */
  8. class CAppVars
  9. {
  10.     friend LRESULT PASCAL MallocWndProc(HWNDUINTWPARAMLPARAM);
  11. protected:
  12.     HINSTANCE   m_hInst;
  13.     HINSTANCE   m_hInstPrev;
  14.     UINT        m_nCmdShow;
  15.     HWND        m_hWnd;
  16.     LPMALLOC    m_pIMalloc;
  17.     BOOL        m_fInitialized;
  18.     ULONG       m_rgcb[CALLOCS];   //Sizes to allocate
  19.     LPVOID      m_rgpv[CALLOCS];   //Allocated pointers
  20. public:
  21.     CAppVars(HINSTANCEHINSTANCEUINT);
  22.     ~CAppVars(void);
  23.     BOOL FInit(void);
  24.     void FreeAllocations(BOOL);
  25. };
  26. typedef CAppVars FAR* LPAPPVARS;
  27. #define CBWNDEXTRA          sizeof(LONG)
  28. #define MALLOCWL_STRUCTURE  0
  29. #endif // _MALLOC_H_

如下是MALLOC.CPP文件内容:

  1. #include <windows.h>
  2. #include <ole2.h>
  3. #include <initguid.h>
  4. #include <ole2ver.h>
  5. #include "malloc.h"
  6. #include "resource.h"
  7. int PASCAL WinMain(HINSTANCE hInst, HINSTANCE hInstPrev, LPSTR pszCmdLine, int nCmdShow)
  8. {
  9.     MSG         msg;
  10.     LPAPPVARS   pAV;
  11.     int         cMsg = 96;
  12. #ifndef WIN32
  13.     while(!SetMessageQueue(cMsg) && (cMsg-=8));
  14. #endif
  15.     pAV = new CAppVars(hInst, hInstPrev, nCmdShow);
  16.     if(NULL == pAV)
  17.     {
  18.         return -1;
  19.     }
  20.     if(pAV->FInit())
  21.     {
  22.         while(GetMessage(&msg, NULL, 0, 0))
  23.         {
  24.             TranslateMessage(&msg);
  25.             DispatchMessage(&msg);
  26.         }
  27.     }
  28.     delete pAV;
  29.     return msg.wParam;
  30. }
  31. LRESULT PASCAL MallocWndProc(HWND hWnd, UINT iMsg, WPARAM wParam, LPARAM lParam)
  32. {
  33.     LPAPPVARS   pAV;
  34.     LPVOID      pv;
  35.     ULONG       cb;
  36.     UINT        i;
  37.     BOOL        fResult = TRUE;
  38.     HRESULT     hr;
  39.     pAV = (LPAPPVARS)GetWindowLong(hWnd, MALLOCWL_STRUCTURE);
  40.     switch(iMsg)
  41.     {
  42.     case WM_NCCREATE:
  43.         pAV = (LPAPPVARS)((LONG)((LPCREATESTRUCT)lParam)->lpCreateParams);
  44.         SetWindowLong(hWnd, MALLOCWL_STRUCTURE, (LONG)pAV);
  45.         return (DefWindowProc(hWnd, iMsg, wParam, lParam));
  46.     case WM_DESTROY:
  47.         PostQuitMessage(0);
  48.         break;
  49.     case WM_COMMAND:
  50.         switch(LOWORD(wParam))
  51.         {
  52.         case IDM_IMALLOCCOGETMALLOCTASK:
  53.             pAV->FreeAllocations(TRUE);
  54.             hr = CoGetMalloc(MEMCTX_TASK, &pAV->m_pIMalloc);
  55.             fResult = SUCCEEDED(hr);
  56.             MessageBox(hWnd, ((fResult)? TEXT("CoGetMalloc(task) succeeded."):TEXT("CoGetMalloc(task) failed.")), 
  57.                 TEXT("MALLOC"), MB_OK);
  58.             break;
  59.         case IDM_IMALLOCCOGETMALLOCSHARED:
  60.             pAV->FreeAllocations(TRUE);
  61.             hr=CoGetMalloc(MEMCTX_SHARED, &pAV->m_pIMalloc);
  62.             fResult = SUCCEEDED(hr);
  63.             MessageBox(hWnd, ((fResult)?TEXT("CoGetMalloc(shared) succeeded."):TEXT("CoGetMalloc(shared) failed.")), 
  64.                 TEXT("MALLOC"), MB_OK);
  65.             break;
  66.         case IDM_IMALLOCRELEASE:
  67.             pAV->FreeAllocations(TRUE);
  68.             MessageBox(hWnd, TEXT("IMalloc::Release finished."), TEXT("Malloc"), MB_OK);
  69.             break;
  70.         case IDM_IMALLOCALLOC:
  71.             if(NULL == pAV->m_pIMalloc)
  72.                 break;
  73.             pAV->FreeAllocations(FALSE);
  74.             for(i=0; i<CALLOCS; i++)
  75.             {
  76.                 LPBYTE  pb;
  77.                 ULONG   iByte;
  78.                 cb = pAV->m_rgcb[i];
  79.                 pAV->m_rgpv[i]=pAV->m_pIMalloc->Alloc(cb);
  80.                 //Fill the memory with letters
  81.                 pb=(LPBYTE)pAV->m_rgpv[i];
  82.                 if(NULL!=pb)
  83.                 {
  84.                     for(iByte=0; iByte<cb; iByte++)
  85.                     {
  86.                         *pb++=('a'+i);
  87.                     }
  88.                 }
  89.                 fResult &= (NULL!=pAV->m_rgpv[i]);
  90.             }
  91.             MessageBox(hWnd, ((fResult)?TEXT("IMalloc::Alloc succeeded."):TEXT("IMalloc::Alloc failed.")), 
  92.                 TEXT("MALLOC"), MB_OK);
  93.             break;
  94.         case IDM_IMALLOCFREE:
  95.             pAV->FreeAllocations(FALSE);
  96.             MessageBox(hWnd, TEXT("IMalloc::Free finished."), TEXT("Malloc"), MB_OK);
  97.             break;
  98.         case IDM_IMALLOCREALLOC:
  99.             if(NULL == pAV->m_pIMalloc)
  100.                 break;
  101.             for(i=0; i<CALLOCS; i++)
  102.             {
  103.                 LPBYTE      pb;
  104.                 ULONG       iByte;
  105.                 pAV->m_rgcb[i]+=128;
  106.                 pv=pAV->m_pIMalloc->Realloc(pAV->m_rgpv[i], pAV->m_rgcb[i]);
  107.                 if(NULL!=pv)
  108.                 {
  109.                     pAV->m_rgpv[i]=pv;
  110.                     //Fill the new memory with something we can see.
  111.                     pb=(LPBYTE)pAV->m_rgpv[i];
  112.                     cb=pAV->m_rgcb[i];
  113.                     if(NULL!=pb)
  114.                     {
  115.                         for(iByte=cb-128; iByte<cb; iByte++)
  116.                         {
  117.                             *pb++=('a'+i);
  118.                         }
  119.                     }
  120.                 }
  121.                 else
  122.                 {
  123.                     fResult  = FALSE;
  124.                 }
  125.             }
  126.             MessageBox(hWnd, ((fResult)?TEXT("IMalloc::Realloc succeeded."):TEXT("IMalloc::Realloc failed.")), 
  127.                 TEXT("Malloc"), MB_OK);
  128.             break;
  129.         case IDM_IMALLOCGETSIZE:
  130.             if(NULL==pAV->m_pIMalloc)
  131.             {
  132.                 break;
  133.             }
  134.             for(i=0; i<CALLOCS; i++)
  135.             {
  136.                 cb = pAV->m_pIMalloc->GetSize(pAV->m_rgpv[i]);
  137.                 /*
  138.                  * We test that the size is at least what we wanted.
  139.                  */
  140.                 fResult &= (pAV->m_rgcb[i] <= cb);
  141.             }
  142.             MessageBox(hWnd, ((fResult)?TEXT("IMalloc::GetSize matched."):TEXT("IMalloc::GetSize mismatch.")),
  143.                 TEXT("Malloc"), MB_OK);
  144.             break;
  145.         case IDM_IMALLOCDIDALLOC:
  146.             if(NULL==pAV->m_pIMalloc)
  147.                 break;
  148.             /*
  149.              * DidAlloc may return -1 if it does not know if
  150.              * it actually allocated something. In that case,
  151.              * we just blindly & in a -1 with no effect.
  152.              */
  153.             for(i=0; i<CALLOCS; i++)
  154.             {
  155.                 fResult &= pAV->m_pIMalloc->DidAlloc(pAV->m_rgpv[i]);
  156.             }
  157.             MessageBox(hWnd, ((fResult)?TEXT("IMalloc::DidAlloc is TRUE."):TEXT("IMalloc::DidAlloc is FALSE.")), 
  158.                 TEXT("IMalloc"), MB_OK);
  159.             break;
  160.         case IDM_IMALLOCHEAPMINIMIZE:
  161.             if(NULL!=pAV->m_pIMalloc)
  162.             {
  163.                 pAV->m_pIMalloc->HeapMinimize();
  164.             }
  165.             MessageBox(hWnd, TEXT("IMalloc::HeapMinimize finished."), TEXT("Malloc"), MB_OK);
  166.             break;
  167.         case IDM_IMALLOCEXIT:
  168.             PostMessage(hWnd, WM_CLOSE, 0, 0L);
  169.             break;
  170.         }
  171.         break;
  172.     default:
  173.         return (DefWindowProc(hWnd, iMsg, wParam, lParam));
  174.     }
  175.     return 0L;
  176. }
  177. CAppVars::CAppVars(HINSTANCE hInst, HINSTANCE hInstPrev, UINT nCmdShow)
  178. {
  179.     UINT    i;
  180.     ULONG   cb;
  181.     //Initialize WinMain parameter holders.
  182.     m_hInst = hInst;
  183.     m_hInstPrev = hInstPrev;
  184.     m_nCmdShow = nCmdShow;
  185.     m_hWnd = NULL;
  186.     m_pIMalloc = NULL;
  187.     m_fInitialized = FALSE;
  188.     
  189.     // 100 is arbitrary. IMalloc can handle larger.
  190.     cb = 100;
  191.     for(i=0; i<CALLOCS; i++)
  192.     {
  193.         m_rgcb[i] = cb;
  194.         m_rgpv[i] = NULL;
  195.         cb*=2;
  196.     }
  197.     return;
  198. }
  199. CAppVars::~CAppVars(void)
  200. {
  201.     FreeAllocations(TRUE);
  202.     //free the enumerator object if we have one.
  203.     if(m_fInitialized)
  204.     {
  205.         CoUninitialize();
  206.     }
  207.     return;
  208. }
  209. BOOL CAppVars::FInit()
  210. {
  211.     WNDCLASS    wc;
  212.     DWORD       dwVer;
  213.     //Make sure COMPOBJ.DLL is the right version
  214.     dwVer = CoBuildVersion();
  215.     if(rmm != HIWORD(dwVer) )
  216.         return FALSE;
  217.     //Call CoInitialize so that we can call other Co... functions
  218.     if(FAILED(CoInitialize(NULL)))
  219.         return FALSE;
  220.     m_fInitialized = TRUE;
  221.     if(!m_hInstPrev)
  222.     {
  223.         wc.style = CS_HREDRAW | CS_VREDRAW;
  224.         wc.lpfnWndProc = MallocWndProc;
  225.         wc.cbClsExtra = 0;
  226.         wc.cbWndExtra = CBWNDEXTRA;
  227.         wc.hInstance = m_hInst;
  228.         wc.hIcon = LoadIcon(m_hInst, TEXT("Icon"));
  229.         wc.hCursor = LoadCursor(NULL, IDC_ARROW);
  230.         wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
  231.         wc.lpszMenuName = MAKEINTRESOURCE(IDR_MENU1);
  232.         wc.lpszClassName = TEXT("MALLOC");
  233.         if(!RegisterClass(&wc))
  234.             return FALSE;
  235.     }
  236.     m_hWnd = CreateWindow(TEXT("MALLOC"), TEXT("IMalloc Object Demo"),
  237.         WS_OVERLAPPEDWINDOW, 35, 35, 350, 250, NULL, NULL, m_hInst, this);
  238.     if(NULL == m_hWnd)
  239.     {
  240.         return FALSE;
  241.     }
  242.     ShowWindow(m_hWnd, m_nCmdShow);
  243.     UpdateWindow(m_hWnd);
  244.     return TRUE;
  245. }
  246. void CAppVars::FreeAllocations(BOOL fRelease)
  247. {
  248.     UINT i;
  249.     if(NULL == m_pIMalloc)
  250.     {
  251.         return;
  252.     }
  253.     for(i=0; i<CALLOCS; i++)
  254.     {
  255.         if(NULL!=m_rgpv[i])
  256.             m_pIMalloc->Free(m_rgpv[i]);
  257.         m_rgpv[i] = NULL;
  258.     }
  259.     if(fRelease)
  260.     {
  261.         m_pIMalloc->Release();
  262.         m_pIMalloc = NULL;
  263.     }
  264. }

任务型内存调用顺序大致如下:

CoGetMalloc(Task,...)

得到任务类型接口指针

Alloc  分配任务型内存
Realloc 再分配,扩充内存
GetSize 得到内存块大小
DidAlloc 确认内存是否已经分配
HeapMinimize 优化堆大小
Free 释放已经分配的内存
Release 释放接口指针

 

共享型内存调用顺序大致如下:

CoGetMalloc(Shared,...)

得到共享类型接口指针

Alloc  分配共享型内存
Realloc 再分配,扩充内存
GetSize 得到内存块大小
DidAlloc 确认内存是否已经分配
HeapMinimize 优化堆大小
Free 释放已经分配的内存
Release 释放接口指针

 

但是很不幸的是,我发现CoGetMalloc, 使用MEMCTX_SHARED即2作为dwMemContext参数进行调用,根本不能成功,如果你强行传入MEMCTX_SHARED,那么你将得到E_INVALIDARG这个错误。也就是说共享类型接口指针根本是胡扯啦~~~

HRESULT CoGetMalloc(DWORD dwMemContext, LPMALLOC * ppMalloc); MSDN上已经明文指定:dwMemContext [in] Reserved; value must be 1.即MEMCTX_TASK。by Loomman, QQ:28077188, MSN: [email protected] QQ裙:30515563 ☆程序天堂☆ 请尊重作者原创,转载注明来自裂帛一剑博客,谢谢合作。

你可能感兴趣的:(优化,command,null,任务,menu,structure)