一区二区三区日韩精品-日韩经典一区二区三区-五月激情综合丁香婷婷-欧美精品中文字幕专区

分享

vc 堆管理函數(shù)

 昵稱3972135 2010-12-19
Windows的“堆”分為默認堆和私有堆兩種。默認堆是在程序初始化時由操作系統(tǒng)自動創(chuàng)建的,所有標準內(nèi)存管理函數(shù)都是在默認堆中申請內(nèi)存的;而私有堆相當于在默認堆中保留了一大塊內(nèi)存,用堆管理函數(shù)可以在這個保留的內(nèi)存區(qū)域中分配內(nèi)存。一個進程的默認堆只有一個,而私有堆可以被創(chuàng)建多個。
 
默認堆可以直接被使用,而私有堆在使用前需要先創(chuàng)建,使用私有堆有很多好處:
1)可以使用默認堆的函數(shù)有多種,而它們可能在不同的線程中同時對默認堆進行操作,為了保持同步,對默認堆的訪問是順序進行的;而私有堆的空間是預(yù)留的,不同線程在不同的私有堆中同時分配內(nèi)存并不會引起沖突,所以整體的運行速度更快。
2)當系統(tǒng)必須在物理內(nèi)存和頁文件之間進行頁面交換時,系統(tǒng)的性能會受到很大的影響,在某些情況下,使用私有堆可以防止系統(tǒng)頻繁地在物理內(nèi)存和交換文件之間進行數(shù)據(jù)交換,因為將經(jīng)常訪問的內(nèi)存局限在一個小范圍地址的話,頁面交換就不大可能發(fā)生,把頻繁訪問的大量小塊內(nèi)存放在同一個私有堆中就可以保證它們在內(nèi)存中的位置更近。
3)使用私有堆有利于封裝和保護模塊化的程序。當程序包含多個模塊時,如果使用標準內(nèi)存管理函數(shù)在默認堆中分配內(nèi)存,那么所有模塊分配的內(nèi)存塊是交叉排列在一起的,如果模塊A中的一個錯誤導(dǎo)致內(nèi)存操作越界,可能會覆蓋模塊B使用的內(nèi)存塊,到模塊B執(zhí)行時出錯,我們將很難發(fā)現(xiàn)錯誤的源頭來自于模塊A。而如果讓不同模塊使用自己的私有堆,那么它們的內(nèi)存就會完全隔離開了,越界錯誤就很容易跟蹤和定位了。
4)使用私有堆使得大量內(nèi)存的清理變得方便,在默認堆中分配的內(nèi)存需要一塊塊單獨釋放,但將一個私有堆釋放后,在這個堆里的內(nèi)存就全部被釋放掉了。并不需要預(yù)先釋放堆棧的每個內(nèi)存塊。
 
私有堆的創(chuàng)建和釋放:
創(chuàng)建私有堆的函數(shù)是HeapCreate:
HANDLE WINAPI HeapCreate(
  __in  DWORD flOptions, //指定堆的屬性:
//HEAP_GENERATE_EXCEPTIONS---指定函數(shù)失敗時返回值,不指定這個標志時,函數(shù)失敗
//時返回NULL、否則返回一個具體的錯誤代碼
         //HEAP_NO_SERIALIZE---控制對私有堆的訪問是否要進行獨占性的檢測;指定這個標志時,
                            //建立堆時不進行獨占性檢測,訪問速度可以更快
  __in  SIZE_T dwInitialSize, //創(chuàng)建堆時分配給堆的物理內(nèi)存(堆的內(nèi)存不足時可以自動擴展)
  __in  SIZE_T dwMaximumSize //能夠擴展到的最大物理內(nèi)存
);
 
如果一個堆不再需要了,可以調(diào)用HeapDestroy函數(shù)將它釋放:
BOOL WINAPI HeapDestroy(
  __in  HANDLE hHeap //堆句柄
);
釋放私有堆可以釋放堆中包含的所有內(nèi)存塊,也可以將堆占用的物理內(nèi)存和保留的地址空間全部返還給系統(tǒng)。如果函數(shù)運行成功,返回值是TRUE;當在進程終止時沒有調(diào)用HeapDestry函數(shù)將私有堆釋放時,系統(tǒng)會自動釋放。
 
 
在堆中分配和釋放內(nèi)存塊:
如果要在堆中分配內(nèi)存塊,可以使用HeapAlloc函數(shù):
LPVOID WINAPI HeapAlloc(
  __in  HANDLE hHeap, //堆句柄
  __in  DWORD dwFlags, //以下標識的組合:HEAP_NO_SERIALIZE HEAP_GENERATE_EXCEPTIONS
                                     //HEAP_ZERO_MEMORY
  __in  SIZE_T dwBytes //需要分配的內(nèi)存塊的字節(jié)數(shù)
);
注意,在堆中分配的內(nèi)存塊只能是固定的內(nèi)存塊,不想GlobalAlloc函數(shù)一樣可以分配可移動的內(nèi)存塊。
 
如果要釋放分配到的內(nèi)存塊,可以使用HeapFree函數(shù):
BOOL WINAPI HeapFree(
  __in  HANDLE hHeap, //堆句柄
  __in  DWORD dwFlags,
  __in  LPVOID lpMem //要釋放的內(nèi)存塊指針,由HeapAlloc或HeapReAlloc返回
);
 
對于用HeapAlloc分配的內(nèi)存塊,可以使用HeapReAlloc函數(shù)重新調(diào)整大?。?/div>
LPVOID WINAPI HeapReAlloc(
  __in  HANDLE hHeap, //堆句柄
  __in  DWORD dwFlags, //以下標識的組合:HEAP_NO_SERIALIZE | HEAP_GENERATE_EXCEPTIONS
                                     //HEAP_ZERO_MEMORY | HEAP_REALLOC_IN_PLACE_ONLY
  __in  LPVOID lpMem, //內(nèi)存塊指針
  __in  SIZE_T dwBytes //新的大小
);
 
其他堆管理函數(shù):
1)GetProcessHeaps函數(shù)用來列出進程中所有的堆:
DWORD WINAPI GetProcessHeaps(
  __in   DWORD NumberOfHeaps, //緩沖區(qū)中可以存放句柄的數(shù)量
  __out  PHANDLE ProcessHeaps //指向用來接收堆句柄的緩沖區(qū)的指針,緩沖區(qū)的長度應(yīng)該等于
                                               //NumberOfHeaps*4字節(jié)
);
函數(shù)執(zhí)行后,進程中所有堆的句柄全部返回到緩沖區(qū)中,其中也包括默認堆的句柄。
 
GetProcessHeap函數(shù)用來獲得進程默認堆的句柄:
HANDLE WINAPI GetProcessHeap(void);
 
 
2)HeapWalk函數(shù)用來列出一個堆中所有內(nèi)存塊:
BOOL WINAPI HeapWalk(
  __in     HANDLE hHeap, //堆句柄
  __inout  LPPROCESS_HEAP_ENTRY lpEntry //指向一個包含PROCESS_HEAP_ENTRY結(jié)構(gòu)的緩沖區(qū)
);
調(diào)用HeapWalk函數(shù)時,函數(shù)每次在PROCESS_HEAP_ENTRY結(jié)構(gòu)中返回一個內(nèi)存塊的信息,如果還有其他內(nèi)存塊,函數(shù)返回TRUE,程序可以一直循環(huán)調(diào)用HeapWalk函數(shù)直到函數(shù)返回FALSE為止。在多線程程序中使用HeapWalk,必須首先使用HeapLock函數(shù)將堆鎖定,否則調(diào)用會失敗。
 
其中PROCESS_HEAP_ENTRY結(jié)構(gòu)如下,它包含了堆元素的信息:
typedef struct _PROCESS_HEAP_ENTRY {
  PVOID lpData; //指向堆元素數(shù)據(jù)區(qū)的指針,初始調(diào)用HeapWalk時,應(yīng)將lpData設(shè)為NULL
  DWORD cbData; //堆元素數(shù)據(jù)區(qū)的字節(jié)大小
  BYTE  cbOverhead; //
  BYTE  iRegionIndex; //
  WORD  wFlags; //
  union {
    struct {
      HANDLE hMem; //
      DWORD  dwReserved[3]; //
    } Block;
    struct {
      DWORD  dwCommittedSize; //
      DWORD  dwUnCommittedSize; //
      LPVOID lpFirstBlock; //
      LPVOID lpLastBlock; //
    } Region;
  } ;
} PROCESS_HEAP_ENTRY, *LPPROCESS_HEAP_ENTRY;
 
3)HeapValidate函數(shù)用來驗證堆的完整性或堆中某個內(nèi)存塊的完整性:
BOOL WINAPI HeapValidate(
  __in      HANDLE hHeap, //要驗證的堆句柄
  __in      DWORD dwFlags, //標志位
  __in_opt  LPCVOID lpMem //為NULL,則函數(shù)順序驗證堆中所有的內(nèi)存塊;
                                     //指定一個內(nèi)存塊,則只驗證這個內(nèi)存塊
);
如果驗證結(jié)果是內(nèi)存塊都完好無損,函數(shù)返回非0值,否則函數(shù)返回0。
 
4)HeapLock和HeapUnlock函數(shù)用來鎖定和解鎖堆,這兩個函數(shù)用于線程的同步:
BOOL WINAPI HeapLock(
  __in  HANDLE hHeap
);
BOOL WINAPI HeapUnlock(
  __in  HANDLE hHeap
);
如果函數(shù)執(zhí)行成功,返回值是非0值,否則返回0。一般來說,很少在程序中使用這兩個函數(shù),而總是使用HEAP_NO_SERIALIZE標志來進行同步控制,指定了這個標志的話,HeapAlloc、HeapReAlloc、HeapSize和HeapFree等函數(shù)會在內(nèi)部自己調(diào)用HeapLock和HeapUnlock函數(shù)。
 
5)HeapSize函數(shù)返回堆中某個內(nèi)存塊的大小,這個大小就是使用HeapAlloc以及HeapReAlloc時指定的大小:
SIZE_T WINAPI HeapSize(
  __in  HANDLE hHeap, //堆句柄
  __in  DWORD dwFlags, //標志位
  __in  LPCVOID lpMem //需要返回大小的內(nèi)存塊
);
 
6)HeapCompact函數(shù)用于合并堆中的空閑內(nèi)存塊并釋放不在使用中的內(nèi)存頁面:
SIZE_T WINAPI HeapCompact(
  __in  HANDLE hHeap,
  __in  DWORD dwFlags
);
 
下面實例代碼使用HeapWalk函數(shù)來遍歷一個堆:
 
#include <windows.h>
#include <tchar.h>
#include <stdio.h>
 
int __cdecl _tmain()
{
    DWORD LastError;
    HANDLE hHeap;
    PROCESS_HEAP_ENTRY Entry;
 
    //
    // Create a new heap with default parameters.
    //
    hHeap = HeapCreate(0, 0, 0);
    if (hHeap == NULL) {
        _tprintf(TEXT("Failed to create a new heap with LastError %d.\n"),
                 GetLastError());
        return 1;
    }
 
    //
    // Lock the heap to prevent other threads from accessing the heap
    // during enumeration.
    //
    if (HeapLock(hHeap) == FALSE) {
        _tprintf(TEXT("Failed to lock heap with LastError %d.\n"),
                 GetLastError());
        return 1;
    }
 
    _tprintf(TEXT("Walking heap %#p...\n\n"), hHeap);
 
    Entry.lpData = NULL;
    while (HeapWalk(hHeap, &Entry) != FALSE) {
        if ((Entry.wFlags & PROCESS_HEAP_ENTRY_BUSY) != 0) {
            _tprintf(TEXT("Allocated block"));
 
            if ((Entry.wFlags & PROCESS_HEAP_ENTRY_MOVEABLE) != 0) {
                _tprintf(TEXT(", movable with HANDLE %#p"), Entry.Block.hMem);
            }
 
            if ((Entry.wFlags & PROCESS_HEAP_ENTRY_DDESHARE) != 0) {
                _tprintf(TEXT(", DDESHARE"));
            }
        }
        else if ((Entry.wFlags & PROCESS_HEAP_REGION) != 0) {
            _tprintf(TEXT("Region\n  %d bytes committed\n") \
                     TEXT("  %d bytes uncommitted\n  First block address: %#p\n") \
                     TEXT("  Last block address: %#p\n"),
                     Entry.Region.dwCommittedSize,
                     Entry.Region.dwUnCommittedSize,
                     Entry.Region.lpFirstBlock,
                     Entry.Region.lpLastBlock);
        }
        else if ((Entry.wFlags & PROCESS_HEAP_UNCOMMITTED_RANGE) != 0) {
            _tprintf(TEXT("Uncommitted range\n"));
        }
        else {
            _tprintf(TEXT("Block\n"));
        }
 
        _tprintf(TEXT("  Data portion begins at: %#p\n  Size: %d bytes\n") \
                 TEXT("  Overhead: %d bytes\n  Region index: %d\n\n"),
                 Entry.lpData,
                 Entry.cbData,
                 Entry.cbOverhead,
                 Entry.iRegionIndex);
    }
    LastError = GetLastError();
    if (LastError != ERROR_NO_MORE_ITEMS) {
        _tprintf(TEXT("HeapWalk failed with LastError %d.\n"), LastError);
    }
 
    //
    // Unlock the heap to allow other threads to access the heap after
    // enumeration has completed.
    //
    if (HeapUnlock(hHeap) == FALSE) {
        _tprintf(TEXT("Failed to unlock heap with LastError %d.\n"),
                 GetLastError());
    }
 
    //
    // When a process terminates, allocated memory is reclaimed by the operating
    // system so it is not really necessary to call HeapDestroy in this example.
    // However, it may be advisable to call HeapDestroy in a longer running
    // application.
    //
    if (HeapDestroy(hHeap) == FALSE) {
        _tprintf(TEXT("Failed to destroy heap with LastError %d.\n"),
                 GetLastError());
    }
 
    return 0;
}
 
下面的實例代碼使用GetProcessHeaps函數(shù)獲得進程中所有堆的句柄:
#include <windows.h>
#include <tchar.h>
#include <stdio.h>
#include <intsafe.h>
 
int __cdecl _tmain()
{
    DWORD NumberOfHeaps;
    DWORD HeapsIndex;
    DWORD HeapsLength;
    HANDLE hDefaultProcessHeap;
    HRESULT Result;
    PHANDLE aHeaps;
    SIZE_T BytesToAllocate;
 
    //
    // Retrieve the number of active heaps for the current process
    // so we can calculate the buffer size needed for the heap handles.
    //
    NumberOfHeaps = GetProcessHeaps(0, NULL);
    if (NumberOfHeaps == 0) {
        _tprintf(TEXT("Failed to retrieve the number of heaps with LastError %d.\n"),
                 GetLastError());
        return 1;
    }
 
    //
    // Calculate the buffer size.
    //
    Result = SIZETMult(NumberOfHeaps, sizeof(*aHeaps), &BytesToAllocate);
    if (Result != S_OK) {
        _tprintf(TEXT("SIZETMult failed with HR %d.\n"), Result);
        return 1;
    }
 
    //
    // Get a handle to the default process heap.
    //
    hDefaultProcessHeap = GetProcessHeap();
    if (hDefaultProcessHeap == NULL) {
        _tprintf(TEXT("Failed to retrieve the default process heap with LastError %d.\n"),
                 GetLastError());
        return 1;
    }
 
    //
    // Allocate the buffer from the default process heap.
    //
    aHeaps = (PHANDLE)HeapAlloc(hDefaultProcessHeap, 0, BytesToAllocate);
    if (aHeaps == NULL) {
        _tprintf(TEXT("HeapAlloc failed to allocate %d bytes.\n"),
                 BytesToAllocate);
        return 1;
    }
 
    //
    // Save the original number of heaps because we are going to compare it
    // to the return value of the next GetProcessHeaps call.
    //
    HeapsLength = NumberOfHeaps;
 
    //
    // Retrieve handles to the process heaps and print them to stdout.
    // Note that heap functions should be called only on the default heap of the process
    // or on private heaps that your component creates by calling HeapCreate.
    //
    NumberOfHeaps = GetProcessHeaps(HeapsLength, aHeaps);
    if (NumberOfHeaps == 0) {
        _tprintf(TEXT("Failed to retrieve heaps with LastError %d.\n"),
                 GetLastError());
        return 1;
    }
    else if (NumberOfHeaps > HeapsLength) {
 
        //
        // Compare the latest number of heaps with the original number of heaps.
        // If the latest number is larger than the original number, another
        // component has created a new heap and the buffer is too small.
        //
        _tprintf(TEXT("Another component created a heap between calls. ") \
                 TEXT("Please try again.\n"));
        return 1;
    }
 
    _tprintf(TEXT("Process has %d heaps.\n"), HeapsLength);
    for (HeapsIndex = 0; HeapsIndex < HeapsLength; ++HeapsIndex) {
        _tprintf(TEXT("Heap %d at address: %#p.\n"),
                 HeapsIndex,
                 aHeaps[HeapsIndex]);
    }
 
    //
    // Release memory allocated from default process heap.
    //
    if (HeapFree(hDefaultProcessHeap, 0, aHeaps) == FALSE) {
        _tprintf(TEXT("Failed to free allocation from default process heap.\n"));
    }
 
    return 0;
}
 
#include "stdafx.h"
#include <windows.h>
#include <iostream.h>

int main(int argc, char* argv[])
{
 //創(chuàng)建堆
 HANDLE hHeap = HeapCreate(
  HEAP_GENERATE_EXCEPTIONS, //排除例外
  10 << 10,     //起始于10K
  10 << 20);     //終止于10K
 if(hHeap != NULL)
 {
  //分配大的塊
  LPVOID pLarge = HeapAlloc(
   hHeap,
   HEAP_ZERO_MEMORY,
   1024);
  //分配小的塊
  LPVOID pSmall = HeapAlloc(
   hHeap,
   HEAP_ZERO_MEMORY,
   1);
  PROCESS_HEAP_ENTRY phe;
  ZeroMemory(&phe, sizeof(phe));
  HeapLock(hHeap);
  while(HeapWalk(hHeap, &phe))
  {
   if(phe.lpData == pLarge)
   {
    cout<<"Found large block"<<endl;
   }
   else if(phe.lpData == pSmall)
   {
    cout<<"Found small block"<<endl;
   }
   else
   {
    cout<<"Anonymous block"<<endl;
   }
  }
  HeapUnlock(hHeap);
  HeapFree(hHeap, 0, pLarge);
  pLarge = NULL;
  HeapFree(hHeap, 0, pSmall);
  pSmall = NULL;
 }
 return 0;
}

    本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊一鍵舉報。
    轉(zhuǎn)藏 分享 獻花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多

    午夜精品一区免费视频| 熟妇人妻av中文字幕老熟妇| 国产精品午夜视频免费观看| 国产精品日韩欧美第一页| 欧美黑人在线精品极品| 又黄又色又爽又免费的视频| 五月激情婷婷丁香六月网| 婷婷色香五月综合激激情| 亚洲国产丝袜一区二区三区四 | 老司机精品一区二区三区| 老鸭窝精彩从这里蔓延| 欧洲日韩精品一区二区三区| 亚洲国产成人精品福利| 国产精品欧美激情在线播放| 在线中文字幕亚洲欧美一区| 福利专区 久久精品午夜| 中文字幕无线码一区欧美| 少妇被粗大进猛进出处故事| 五月婷婷综合缴情六月| 免费播放一区二区三区四区| 久热青青草视频在线观看| 91国内视频一区二区三区| 国产成人精品一区二区在线看| 精品熟女少妇av免费久久野外| 亚洲视频一区二区久久久| 日韩人妻中文字幕精品| 亚洲天堂精品一区二区| 亚洲美女国产精品久久| 久久91精品国产亚洲| 欧美精品亚洲精品一区| 在线观看视频日韩成人| 日本一区二区三区黄色| 欧美成人一区二区三区在线| 欧美日韩最近中国黄片| 亚洲av日韩av高潮无打码| 小草少妇视频免费看视频| 免费特黄欧美亚洲黄片| 五月天丁香婷婷狠狠爱| 国产在线观看不卡一区二区| 国产av精品高清一区二区三区| 色综合久久中文综合网|