2.12 内存管理

大家学习C语言的时候,都知道可以用CRT库中函数malloc来分配内存空间,用free函数来释放内存空间。但在某些场合,比如CreateThread创建的线程函数中是不能使用CRT库函数的,此时如果要申请内存怎么办呢?方法是使用Windows API内存管理函数,这些内存管理函数效率高,但无法移植到非Windows平台。常见的内存管理API函数如下:

(1)HeapAlloc函数

该函数用来申请一块内存堆空间,函数声明如下:

        LPVOID HeapAlloc(  HANDLE  hHeap,  DWORD dwFlags,  SIZE_T dwBytes);

其中参数hHeap是内存空间堆的句柄,函数将在该堆上开辟一块内存空间,这个句柄值可以由函数HeapCreate或GetProcessHeap来获得;dwFlags是堆分配控制的标记,可以取下列值:

● HEAP_GENERATE_EXCEPTIONS:如果函数失败,系统将会抛出异常。

● HEAP_NO_SERIALIZE:这次分配的空间不允许串行访问。

● HEAP_ZERO_MEMORY:分配的内存将初始化为零,不指定该标记,内存将不会初始化为零。

● dwBytes:为要分配的空间的字节数。如果函数成功,返回指向分配的内存块的指针;否则如果没有指定标记HEAP_GENERATE_EXCEPTIONS,将返回NULL。

注意HeapAlloc分配的内存要用函数HeapFree来释放。

(2)HeapFree函数

该函数用来释放由HeapAlloc分配的空间,函数声明如下:

        BOOL  HeapFree( HANDLE hHeap,  DWORD dwFlags, LPVOID lpMem);

其中参数hHeap为内存空间堆的句柄;dwFlags为堆释放的选项;lpMem为指向要释放的内存块指针。如果函数成功,返回非零;否则返回零。

(3)GetProcessHeap函数

该函数获得调用进程的默认内存堆句柄。函数声明如下:

        HANDLE  GetProcessHeap();

函数返回调用进程的默认内存堆句柄。

【例2.51】 分配内存堆并释放

(1)新建一个控制台工程。

(2)在Test.cpp中输入代码如下:

        #include "stdafx.h"
        #include <windows.h>
        #include <strsafe.h>
        typedef struct _MyData {  //定义传给线程的参数的类型
            int val1;
            int val2;
        } MYDATA, *PMYDATA;
        #define BUF_SIZE 100
        int _tmain(int argc, _TCHAR* argv[])
        {
            HANDLE hStdout;
            PMYDATA pData;
            TCHAR msgBuf[BUF_SIZE];
            size_t cchStringSize;
            DWORD dwChars;
            hStdout = GetStdHandle(STD_OUTPUT_HANDLE); //得到标准输出设备的句柄,为了打印
            if (hStdout == INVALID_HANDLE_VALUE)
                return -1;
            //申请堆空间
            pData      =      (PMYDATA)HeapAlloc(GetProcessHeap(),      HEAP_ZERO_MEMORY,sizeof(MYDATA));
            if (pData == NULL) //如果分配失败,则结束进程
                ExitProcess(2);
            pData->val1 = 10;
            pData->val2 = 20;
            StringCchPrintf(msgBuf, BUF_SIZE, _T("结果:%d, %d\n"), //构造字符串
                pData->val1, pData->val2);
            StringCchLength(msgBuf, BUF_SIZE, &cchStringSize); //得到字符串长度,存于cchStringSize
            WriteConsole(hStdout, msgBuf, cchStringSize, &dwChars, NULL); //在终端窗口输出字符串
            HeapFree(GetProcessHeap(), 0, pData); //释放分配的堆空间
        }

(3)保存工程并运行,运行结果如图2-105所示。

图2-105