• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>

            C++ Programmer's Cookbook

            {C++ 基礎(chǔ)} {C++ 高級(jí)} {C#界面,C++核心算法} {設(shè)計(jì)模式} {C#基礎(chǔ)}

            windows核心編程--內(nèi)存堆棧

            對(duì)內(nèi)存進(jìn)行操作的第三個(gè)機(jī)制是使用堆棧。堆??梢杂脕?lái)分配許多較小的數(shù)據(jù)塊。例如,若要對(duì)鏈接表和鏈接樹(shù)進(jìn)行管理,最好的方法是使用堆棧,堆棧的優(yōu)點(diǎn)是,可以不考慮分配粒度和頁(yè)面邊界之類的問(wèn)題,集中精力處理手頭的任務(wù)。堆棧的缺點(diǎn)是,分配和釋放內(nèi)存塊的速度比其他機(jī)制要慢,并且無(wú)法直接控制物理存儲(chǔ)器的提交和回收。
            從內(nèi)部來(lái)講,堆棧是保留的地址空間的一個(gè)區(qū)域。開(kāi)始時(shí),保留區(qū)域中的大多數(shù)頁(yè)面沒(méi)有被提交物理存儲(chǔ)器。當(dāng)從堆棧中進(jìn)行越來(lái)越多的內(nèi)存分配時(shí),堆棧管理器將把更多的物理存儲(chǔ)器提交給堆棧。物理存儲(chǔ)器總是從系統(tǒng)的頁(yè)文件中分配的,當(dāng)釋放堆棧中的內(nèi)存塊時(shí),堆棧管理器將收回這些物理存儲(chǔ)器。

            線程的堆棧:

            每當(dāng)創(chuàng)建一個(gè)線程時(shí),系統(tǒng)就會(huì)為線程的堆棧(每個(gè)線程有它自己的堆棧)保留一個(gè)堆棧空間區(qū)域,并將一些物理存儲(chǔ)器提交給這個(gè)已保留的區(qū)域。按照默認(rèn)設(shè)置,系統(tǒng)保留1 MB的地址空間并提交兩個(gè)頁(yè)面的內(nèi)存。但是,這些默認(rèn)值是可以修改的,方法是在你鏈接應(yīng)用程序時(shí)設(shè)定M i c r o s o f t的鏈接程序的/ S TA C K選項(xiàng):

            /STACK:reserve[,commit]

            當(dāng)創(chuàng)建一個(gè)線程的堆棧時(shí),系統(tǒng)將會(huì)保留一個(gè)鏈接程序的/ S TA C K開(kāi)關(guān)指明的地址空間區(qū)域。
            進(jìn)程的默認(rèn)堆棧

            當(dāng)進(jìn)程初始化時(shí),系統(tǒng)在進(jìn)程的地址空間中創(chuàng)建一個(gè)堆棧。該堆棧稱為進(jìn)程的默認(rèn)堆棧。按照默認(rèn)設(shè)置,該堆棧的地址空間區(qū)域的大小是1 MB。但是,系統(tǒng)可以擴(kuò)大進(jìn)程的默認(rèn)堆棧,使它大于其默認(rèn)值。當(dāng)創(chuàng)建應(yīng)用程序時(shí),可以使用/ H E A P鏈接開(kāi)關(guān),改變堆棧的1 M B默認(rèn)區(qū)域大小。由于D L L沒(méi)有與其相關(guān)的堆棧,所以當(dāng)鏈接D L L時(shí),不應(yīng)該使用/ H E A P鏈接開(kāi)關(guān)。/ H E A P鏈接開(kāi)關(guān)的句法如下:

            /HEAP:reserve[,commit]

            許多Wi n d o w s函數(shù)要求進(jìn)程使用其默認(rèn)堆棧。特別是widows提供的API。對(duì)默認(rèn)堆棧的訪問(wèn)是順序進(jìn)行的。換句話說(shuō),系統(tǒng)必須保證在規(guī)定的時(shí)間內(nèi),每次只有一個(gè)線程能夠分配和釋放默認(rèn)堆棧中的內(nèi)存塊。如果兩個(gè)線程試圖同時(shí)分配默認(rèn)堆棧中的內(nèi)存塊,那么只有一個(gè)線程能夠分配內(nèi)存塊,另一個(gè)線程必須等待第一個(gè)線程的內(nèi)存塊分配之后,才能分配它的內(nèi)存塊。一旦第一個(gè)線程的內(nèi)存塊分配完,堆棧函數(shù)將允許第二個(gè)線程分配內(nèi)存塊。這種順序訪問(wèn)方法對(duì)速度有一定的影響。如果你的應(yīng)用程序只有一個(gè)線程,并且你想要以最快的速度訪問(wèn)堆棧,那么應(yīng)該創(chuàng)建你自己的獨(dú)立的堆棧,不要使用進(jìn)程的默認(rèn)堆棧。

            單個(gè)進(jìn)程可以同時(shí)擁有若干個(gè)堆棧。這些堆??梢栽谶M(jìn)程的壽命期中創(chuàng)建和撤消。但是,默認(rèn)堆棧是在進(jìn)程開(kāi)始執(zhí)行之前創(chuàng)建的,并且在進(jìn)程終止運(yùn)行時(shí)自動(dòng)被撤消。不能撤消進(jìn)程的默認(rèn)堆棧。每個(gè)堆棧均用它自己的堆棧句柄來(lái)標(biāo)識(shí),用于分配和釋放堆棧中的內(nèi)存塊的所有堆棧函數(shù)都需要這個(gè)堆棧句柄作為其參數(shù)。

            可以通過(guò)調(diào)用G e t P r o c e s s H e a p函數(shù)獲取你的進(jìn)程默認(rèn)堆棧的句柄:

            HANDLE GetProcessHeap();

            為什么要?jiǎng)?chuàng)建輔助堆棧

            除了進(jìn)程的默認(rèn)堆棧外,可以在進(jìn)程的地址空間中創(chuàng)建一些輔助堆棧。由于下列原因,你可能想要在自己的應(yīng)用程序中創(chuàng)建一些輔助堆棧:

            ? 保護(hù)組件。

            ? 更加有效地進(jìn)行內(nèi)存管理。

            ? 進(jìn)行本地訪問(wèn)。

            ? 減少線程同步的開(kāi)銷。

            ? 迅速釋放。

            保護(hù)組件
            通過(guò)創(chuàng)建多個(gè)獨(dú)立的堆棧,是數(shù)據(jù)隔離,且相互獨(dú)立的操作。
            更有效的內(nèi)存管理

            通過(guò)在堆棧中分配同樣大小的對(duì)象,就可以更加有效地管理堆棧。就是把大小相同的對(duì)象放在一個(gè)堆棧中進(jìn)行分配。
            進(jìn)行本地訪問(wèn)

            每當(dāng)系統(tǒng)必須在R A M與系統(tǒng)的頁(yè)文件之間進(jìn)行R A M頁(yè)面的交換時(shí),系統(tǒng)的運(yùn)行性能就會(huì)受到很大的影響。如果經(jīng)常訪問(wèn)局限于一個(gè)小范圍地址的內(nèi)存,那么系統(tǒng)就不太可能需要在R A M與磁盤之間進(jìn)行頁(yè)面的交換。

            所以,在設(shè)計(jì)應(yīng)用程序的時(shí)候,如果有些數(shù)據(jù)將被同時(shí)訪問(wèn),那么最好把它們分配在互相靠近的位置上。
            減少線程同步的開(kāi)銷

            正如下面就要介紹的那樣,按照默認(rèn)設(shè)置,堆棧是順序運(yùn)行的,這樣,如果多個(gè)線程試圖同時(shí)訪問(wèn)堆棧,就不會(huì)使數(shù)據(jù)受到破壞。但是,堆棧函數(shù)必須執(zhí)行額外的代碼,以保證堆棧對(duì)線程的安全性。如果要進(jìn)行大量的堆棧分配操作,那么執(zhí)行這些額外的代碼會(huì)增加很大的負(fù)擔(dān),從而降低你的應(yīng)用程序的運(yùn)行性能。當(dāng)你創(chuàng)建一個(gè)新堆棧時(shí),可以告訴系統(tǒng),只有一個(gè)線程將訪問(wèn)該堆棧,因此額外的代碼將不執(zhí)行。(就是用多個(gè)堆棧來(lái)減少同步的性能消耗)
            迅速釋放堆棧

            最后要說(shuō)明的是,將專用堆棧用于某些數(shù)據(jù)結(jié)構(gòu)后,就可以釋放整個(gè)堆棧,而不必顯式釋放堆棧中的每個(gè)內(nèi)存塊。例如,當(dāng)Windows Explorer遍歷硬盤驅(qū)動(dòng)器的目錄層次結(jié)構(gòu)時(shí),它必須在內(nèi)存中建立一個(gè)樹(shù)狀結(jié)構(gòu)。如果你告訴Windows Explorer刷新它的顯示器,它只需要撤消包含這個(gè)樹(shù)狀結(jié)構(gòu)的堆棧并且重新運(yùn)行即可(當(dāng)然,假定它將專用堆棧用于存放目錄樹(shù)信息)。對(duì)于許多應(yīng)用程序來(lái)說(shuō),這是非常方便的,并且它們也能更快地運(yùn)行。

            如何創(chuàng)建輔助堆棧

            你可以在進(jìn)程中創(chuàng)建輔助堆棧,方法是讓線程調(diào)用H e a p C r e a t e函數(shù):

            HANDLE HeapCreate(
               DWORD fdwOptions,
               SIZE_T dwInitialSize,
               SIZE_T dwMaximumSize);

            當(dāng)試圖從堆棧分配一個(gè)內(nèi)存塊時(shí), H e a p A l l o c函數(shù)(下面將要介紹)必須執(zhí)行下列操作:

            1) 遍歷分配的和釋放的內(nèi)存塊的鏈接表。

            2) 尋找一個(gè)空閑內(nèi)存塊的地址。

            3) 通過(guò)將空閑內(nèi)存塊標(biāo)記為“已分配”分配新內(nèi)存塊。

            4) 將新內(nèi)存塊添加給內(nèi)存塊鏈接表。

            從堆棧中分配內(nèi)存塊

            若要從堆棧中分配內(nèi)存塊,只需要調(diào)用H e a p A l l o c函數(shù):

            PVOID HeapAlloc(
               HANDLE hHeap,
               DWORD fdwFlags,
               SIZE_T dwBytes);

            改變內(nèi)存塊的大小

            常常需要改變內(nèi)存塊的大小。有些應(yīng)用程序開(kāi)始時(shí)分配的內(nèi)存塊比較大,然后,當(dāng)所有數(shù)據(jù)放入內(nèi)存塊后,再縮小內(nèi)存塊的大小。有些應(yīng)用程序開(kāi)始時(shí)分配的內(nèi)存塊比較小,后來(lái)需要將更多的數(shù)據(jù)拷貝到內(nèi)存塊中去時(shí),再設(shè)法擴(kuò)大它的大小。如果要改變內(nèi)存塊的大小,可以調(diào)用H e a p R e A l l o c函數(shù):

            PVOID HeapReAlloc(
               HANDLE hHeap,
               DWORD fdwFlags,
               PVOID pvMem,
               SIZE_T dwBytes);

            了解內(nèi)存塊的大小

            當(dāng)內(nèi)存塊分配后,可以調(diào)用H e a p S i z e函數(shù)來(lái)檢索內(nèi)存塊的實(shí)際大?。?/font>

            SIZE_T HeapSize(
               HANDLE hHeap,
               DWORD fdwFlags,
               LPCVOID pvMem);

            釋放內(nèi)存塊

            當(dāng)不再需要內(nèi)存塊時(shí),可以調(diào)用H e a p F r e e函數(shù)將它釋放:

            BOOL HeapFree(
               HANDLE hHeap,
               DWORD fdwFlags,
               PVOID pvMem);

            撤消堆棧

            如果應(yīng)用程序不再需要它創(chuàng)建的堆棧,可以通過(guò)調(diào)用H e a p D e s t r o y函數(shù)將它撤消:

            BOOL HeapDestroy(HANDLE hHeap);

            調(diào)用H e a p D e s t r o y函數(shù)可以釋放堆棧中包含的所有內(nèi)存塊,也可以將堆棧占用的物理存儲(chǔ)器和保留的地址空間區(qū)域重新返回給系統(tǒng)。如果該函數(shù)運(yùn)行成功, H e a p D e s t r o y返回T R U E。如果在進(jìn)程終止運(yùn)行之前沒(méi)有顯式撤消堆棧,那么系統(tǒng)將為你將它撤消。但是,只有當(dāng)進(jìn)程終止運(yùn)行時(shí),堆棧才能被撤消。如果線程創(chuàng)建了一個(gè)堆棧,當(dāng)線程終止運(yùn)行時(shí),該堆棧將不會(huì)被撤消。

            在進(jìn)程完全終止運(yùn)行之前,系統(tǒng)不允許進(jìn)程的默認(rèn)堆棧被撤消。如果將進(jìn)程的默認(rèn)堆棧的句柄傳遞給H e a p D e s t r o y函數(shù),系統(tǒng)將忽略對(duì)該函數(shù)的調(diào)用。

            由于進(jìn)程的地址空間中可以存在多個(gè)堆棧,因此可以使用G e t P r o c e s s H e a p s函數(shù)來(lái)獲取現(xiàn)有堆棧的句柄:

            DWORD GetProcessHeaps(
               DWORD dwNumHeaps,
               PHANDLE pHeaps);

            若要調(diào)用G e t P r o c e s s H e a p s函數(shù),必須首先分配一個(gè)H A N D L E數(shù)組,然后調(diào)用下面的函數(shù):

            HANDLE hHeaps[25];
            DWORD dwHeaps = GetProcessHeaps(25, hHeaps);
            if(dwHeaps > 5) 
            {
               //More heaps are in this process than we expected.
            } 
            else
            {
               //hHeaps[0] through hHeap[dwHeaps - 1]
               //identify the existing heaps.
            }

            注意,當(dāng)該函數(shù)返回時(shí),你的進(jìn)程的默認(rèn)堆棧的句柄也包含在堆棧句柄的數(shù)組中。

            H e a p Va l i d a t e函數(shù)用于驗(yàn)證堆棧的完整性:

            BOOL HeapValidate(
               HANDLE hHeap,
               DWORD fdwFlags,
               LPCVOID pvMem);

            調(diào)用該函數(shù)時(shí),通常要傳遞一個(gè)堆棧句柄,一個(gè)值為0的標(biāo)志(唯一的另一個(gè)合法標(biāo)志是H E A P _ N O _ S E R I A L I Z E),并且為p v M e m傳遞N U L L。然后,該函數(shù)將遍歷堆棧中的內(nèi)存塊以確保所有內(nèi)存塊都完好無(wú)損。為了使該函數(shù)運(yùn)行得更快,可以為參數(shù)p v M e m傳遞一個(gè)特定的內(nèi)存塊的地址。這樣做可使該函數(shù)只檢查單個(gè)內(nèi)存塊的有效性。

            若要合并地址中的空閑內(nèi)存塊并收回不包含已經(jīng)分配的地址內(nèi)存塊的存儲(chǔ)器頁(yè)面,可以調(diào)用下面的函數(shù):

            UINT HeapCompact(
               HANDLE hHeap,
               DWORD fdwFlags);
            

            通常情況下,可以為參數(shù)f d w F l a g s傳遞0,但是也可以傳遞H E A P _ N O _ S E R I A L I Z E。

            下面兩個(gè)函數(shù)H e a p L o c k和H e a p U n l o c k是結(jié)合在一起使用的:

            BOOL HeapLock(HANDLE hHeap);
            BOOL HeapUnlock(HANDLE hHeap);

            這些函數(shù)是用于線程同步的。當(dāng)調(diào)用H e a p L o c k函數(shù)時(shí),調(diào)用線程將成為特定堆棧的所有者。如果其他任何線程調(diào)用堆棧函數(shù)(設(shè)定相同的堆棧句柄),系統(tǒng)將暫停調(diào)用線程的運(yùn)行,并且在堆棧被H e a p U n l o c k函數(shù)解鎖之前不允許它醒來(lái)。

            H e a p A l l o c、H e a p S i z e和H e a p F r e e等函數(shù)在內(nèi)部調(diào)用H e a p L o c k和H e a p U n l o c k函數(shù)來(lái)確保對(duì)堆棧的訪問(wèn)能夠順序進(jìn)行。自己調(diào)用H e a p L o c k或H e a p U n l o c k這種情況是不常見(jiàn)的。

            最后一個(gè)堆棧函數(shù)是H e a p Wa l k:

            BOOL HeapWalk(
               HANDLE hHeap,
               PPROCESS_HEAP_ENTRY pHeapEntry);

            該函數(shù)只用于調(diào)試目的。它使你能夠遍歷堆棧的內(nèi)容??梢远啻握{(diào)用該函數(shù)。

            zz


            posted on 2006-09-21 16:24 夢(mèng)在天涯 閱讀(4344) 評(píng)論(0)  編輯 收藏 引用 所屬分類: Windows API

            公告

            EMail:itech001#126.com

            導(dǎo)航

            統(tǒng)計(jì)

            • 隨筆 - 461
            • 文章 - 4
            • 評(píng)論 - 746
            • 引用 - 0

            常用鏈接

            隨筆分類

            隨筆檔案

            收藏夾

            Blogs

            c#(csharp)

            C++(cpp)

            Enlish

            Forums(bbs)

            My self

            Often go

            Useful Webs

            Xml/Uml/html

            搜索

            •  

            積分與排名

            • 積分 - 1807503
            • 排名 - 5

            最新評(píng)論

            閱讀排行榜

            精品久久久久久久久中文字幕| 亚洲Av无码国产情品久久| 一本久久a久久精品vr综合| 色欲久久久天天天综合网精品| 无码AV中文字幕久久专区| 久久久久久综合一区中文字幕| 国产精品久久久久久福利漫画 | 久久综合狠狠色综合伊人| 久久天天日天天操综合伊人av| 亚洲国产精品无码久久一线| 青青草原综合久久大伊人精品| 久久受www免费人成_看片中文| 99re久久精品国产首页2020| 午夜福利91久久福利| 久久精品九九亚洲精品天堂 | 久久国产午夜精品一区二区三区| 久久精品免费一区二区| 久久国产精品视频| 国产精品一久久香蕉国产线看观看| 深夜久久AAAAA级毛片免费看| 国产精品99久久99久久久| 无码人妻久久一区二区三区蜜桃| 久久国产成人午夜AV影院| 久久精品国产一区| 久久99国产精一区二区三区| 精品熟女少妇AV免费久久| 香港aa三级久久三级老师2021国产三级精品三级在 | 2020最新久久久视精品爱| 久久久久人妻一区二区三区 | 久久国产免费观看精品3| 少妇人妻综合久久中文字幕| 亚洲国产精品无码久久SM| 91精品国产91久久| 久久久婷婷五月亚洲97号色| 精品久久久久久久久午夜福利| 精品久久久久中文字幕一区| 一本色道久久HEZYO无码| 无码精品久久久久久人妻中字| 狠狠色综合久久久久尤物 | 四虎国产精品免费久久5151| 99久久超碰中文字幕伊人|