標籤:style blog http color 使用 os io strong
尋找了一些 new , GlobalAlloc, HeapAlloc分配記憶體方式的區別。
轉了一些資料
//===========================================================//
下面是資料1:
1. GlobalAlloc函數和new()的區別。
1>new是標準的C++分配記憶體函數。GlobalAlloc是WIN下的API函數。
2>new分配記憶體同時會調用類等對象的建構函式。GlobalAlloc不回。
3>new分配的記憶體只能同進程使用,如(A進程new,B進程不能delete),GlobalAlloc能多進程使用,並刪除。
2. GlobalAlloc分配的記憶體需要釋放嗎?
所有動態記憶體分配都必須釋放,GlobalAlloc分配的記憶體用GlobalFree進行釋放。
3. GlobalAlloc和HeapAlloc的關係
GlobalAlloc是win16留下來的函數,它調用HeapAlloc分配堆中的記憶體。在理想的win32環境下,我們不需要GlobalAlloc,但是實際上,我們還得保留從win16移植過來的許多代碼。在這些代碼中使用了“記憶體控制代碼”(HGLOBAL)參數而不是32位的記憶體位址。
GlobalAlloc根據其屬性參數做兩件不同的事情。如果參數指定了GMEM_FIXED,則GlobalAlloc簡單調用HeapAlloc,把返回地址作為一個32位HGLOBAL值;如果參數指定了GMEM_MOVEABLE,則返回的HGLOBAL值是一個指向進程裡控制代碼表中某一項入口的指標,該入口包含指向實際HeapAlloc分配的記憶體的指標。
從本質上,如果我們不調用GlobalReAlloc函數,我們就可以用HeapAlloc代替GlobalAlloc。
//==================///
下面是資料2:
GlobalAlloc是標準記憶體管理函數,標準記憶體管理函數都是操作進程的預設堆,所以這個函數是從進程的從進程的預設堆中分配記憶體空間,分配的空間可以是可移動的也可以是不可以移動的。可移動的記憶體是指windows在需要的時候可以將這個記憶體移動到另外一個地址
HeapAllock是堆管理函數,堆管理函數可以操作非預設堆(當然也可以操作預設堆),建立一個堆是用HeapCreate,這個函數返回一個堆控制代碼,然後可以用在HeapAllock函數中,即從返回的這個堆中申請記憶體空間,HeapAllock申請的記憶體只能是不可以移動的
而new則是c++的標準函數,在windows的vc++編譯器中,new在申請記憶體最終調用的是GlabalAllock,不過new還會調用類的建構函式。
windows的記憶體管理除了標準記憶體管理函數和堆管理函數之外,還有更加底層的虛擬記憶體管理函數,VirtualAllock就是一個虛擬記憶體管理函數。
//======================================================//
下面是資料3: 來自:http://blog.csdn.net/jianxiong8814/article/details/1560288
關於更多內容,如果你英語還可以的話,建議不閱讀一下內容,直接進入以下連結
http://msdn2.microsoft.com/en-us/library/aa366723.aspx
malloc()與 alloc()
C語言跟記憶體配置方式(1) 從靜態儲存地區分配。記憶體在程式編譯的時候就已經分配好,這塊記憶體在程式的整個運行期間都存在。例如全域變數,static變數。(2) 在棧上建立。在執行函數時,函數內局部變數的儲存單元都可以在棧上建立,函數執行結束時這些儲存單元自動被釋放。棧記憶體配置運算內建於處理器的指令集中,效率很高,但是分配的記憶體容量有限。(3)從堆上分配,亦稱動態記憶體分配。程式在啟動並執行時候用malloc或new申請任意多少的記憶體,程式員自己負責在何時用free或delete釋放記憶體。動態記憶體的生存期由我們決定,使用非常靈活,但問題也最多C語言跟記憶體申請相關的函數主要有 alloca,calloc,malloc,free,realloc,sbrk等.其中alloca是向棧申請記憶體,因此無需釋放. malloc分配的記憶體是位於堆中的,並且沒有初始化記憶體的內容,因此基本上malloc之後,調用函數memset來初始化這部分的記憶體空間.calloc則將初始化這部分的記憶體,設定為0. 而realloc則對malloc申請的記憶體進行大小的
調整.申請的記憶體最終需要通過函數free來釋放. 而sbrk則是增加資料區段的大小;
malloc/calloc/free基本上都是C函數庫實現的,跟OS無關.C函數庫內部通過一定的結構來儲存當前有多少可用記憶體.如果程式malloc的大小超出了庫裡所留存的空間,那麼將首先調用brk系統調用來增加可用空間,然後再分配空間.free時,釋放的記憶體並不立即返回給os,而是保留在內部結構中. 可以打個比方: brk類似於批發,一次性的向OS申請大的記憶體,而malloc等函數則類似於零售,滿足程式運行時的要求.這套機制類似於緩衝.使用這套機制的原因: 系統調用不能支援任意大小的記憶體配置(有的系統調用只支援固定大小以及其倍數的記憶體申請,這樣的話,對於小記憶體的分配會造成浪費; 系統調用申請記憶體代價昂貴,涉及到使用者態和核心態的轉換.函數malloc()和calloc()都可以用來分配動態記憶體空間,但兩者稍有區別。 malloc()函數有一個參數,即要分配的記憶體空間的大小: Void *malloc(size_t size); calloc()函數有兩個參數,分別為元素的數目和每個元素的大小,這兩個參數的乘積就是要分配的記憶體空間的大小: void *calloc(size_t numElements,size_t sizeOfElement); 如果調用成功,函數malloc()和calloc()都將返回所分配的記憶體空間的首地址。 malloc() 函數和calloc()函數的主要區別是前者不能初始化所分配的記憶體空間,而後者能。如果由malloc()函數分配的記憶體空間原來沒有被使用過,則其中的每一位可能都是0;反之,如果這部分記憶體空間曾經被分配、釋放和重新分配,則其中可能遺留各種各樣的資料。也就是說,使用malloc()函數的程式開始時(記憶體空間還沒有被重新分配)能正常運行,但經過一段時間後(記憶體空間已被重新分配)可能會出現問題。 calloc() 函數會將所分配的記憶體空間中的每一位都初始化為零,也就是說,如果你是為字元類型或整數類型的元素分配記憶體,那麼這些元素將保證會被初始化為零;如果你是為指標類型的元素分配記憶體,那麼這些元素通常(但無法保證)會被初始化為空白指標;如果你是為實數類型的元素分配記憶體,那麼這些元素可能(只在某些電腦中)會被初始化為浮點型的零。 malloc() 函數和calloc()函數的另一點區別是calloc()函數會返回一個由某種對象組成的數組,但malloc()函數只返回一個對象。為了明確是為一個數組分配記憶體空間,有些程式員會選用calloc()函數。但是,除了是否初始化所分配的記憶體空間這一點之外,絕大多數程式員認 為以下兩種函數調用方式沒有區別: calloc(numElements ,sizeOfElement); malloc(numElements *sizeOfElement) ; 需要解釋的一點是,理論上(按照ANSIC標準)指標的算術運算只能在一個指定的數組中進行,但是在實踐中,即使C編譯器或翻譯器遵循這種規定,許多C程式還是衝破了這種限制。因此,儘管malloc()函數並不能返回一個數組,它所分配的記憶體空間仍然能供一個數組使用(對realloc()函數來說同樣如此,儘管它也不能返回一個數組)。 總之,當你在calloc()函數和malloc()函數之間作選擇時,你只需考慮是否要初始化所分配的記憶體空間,而不用考慮函數是否能返回一個數組。 當程式運行過程中malloc了,但是沒有free的話,會造成記憶體流失.一部分的記憶體沒有被使用,但是由於沒有free,因此系統認為這部分記憶體還在使用,造成不斷的向系統申請記憶體,是的系統可用記憶體不斷減少.但是,記憶體流失僅僅指程式在運行時,程式退出時,OS將回收所有的資源.因此,適當的重起一下程式,有時候還是有點作用.
=====================================================
用GlobalAlloc函數來分配記憶體
GlobalAlloc函數接受兩個參數。第一個是一個標誌,指定幾種分配方式中的一種。
GMEM_FIXED = 0x0000分配固定記憶體.
GMEM_MOVEABLE = 0x0002分配可移動記憶體.
GMEM_ZEROINIT = 0x0040初始化記憶體內容,為0.
GPTR = 0x0040 Combines GMEM_FIXED and GMEM_ZEROINIT.
GHND = 0x0042 Combines GMEM_MOVEABLE and GMEM_ZEROINIT.
例如:使用GPTR=0x0040來分配固定記憶體,並將它初始化為0。
GlobalAlloc的第二個參數是要分配的位元組數。如果分配成功,GlobalAlloc返回IntPtr.Zero(大致等於Unmanaged 程式碼的null)。
由於某些原因,分配可能會出現失敗;GlobalAlloc函數是從堆上分配指定的位元組數。
|
|
|
GlobalAlloc 強調全域分配,
但既然都是從堆中分配記憶體, new應該也是全域的啊~~~
不解 。。。。 :confused: |
GlobalAlloc 和 new 兩者用途根本不同啊。
new 和 delete的用法如下:
void *operator new (size_t) throw (std::bad_alloc);
void *operator new[] (size_t) throw (std::bad_alloc);
void operator delete (void *) throw();
void operator delete[] (void *) throw();
void *operator new (size_t, const std::nothrow_t&) throw();
void *operator new[] (size_t, const std::nothrow_t&) throw();
void operator delete (void *, const std::nothrow_t&) throw();
void operator delete[] (void *, const std::nothrow_t&) throw();
使用new和delete對一個進程中的兩個模組進行跨模組的記憶體開闢和釋放,程式可能被崩潰,使用GlobalAlloc開闢記憶體不存在這個問題。
一般除了在剪貼簿等函數中使用GlobalAlloc函數返回的控制代碼外,在其它地方使用GlobalAlloc函數的地方不多啊。
首先GlobalAlloc是winxx的一個api函數,new是c++的一個操作符。
new可以根據作業系統有不同的實現,但是無論他怎麼實現,在一個進程中開闢的記憶體只有該進程才能訪問。
但是GlobalAlloc不同,在一個進程中建立的記憶體,可以被其他進程調用。這就是GlobalAlloc的全域概念,和new是不一樣的。
GlobalAlloc已經不提倡使用為了與16位的程式相容而保留的,new是一個操作符,用來在free store 分配記憶體塊,在windows的CRT實現中,new 操作符通常會先在進程所在的預設堆中分配記憶體調用順序好像是(new(....)->malloc(....)->HeapAlloc(...))最終還是調用windowsAPI的所謂heap 函數來分配記憶體
=============================================================================== heapalloc,globalalloc,virtualalloc,new的異同?樓主sjy()2001-02-02 23:00:00 在 VC/MFC / 基礎類 提問
以上幾個函數都可用於分配記憶體,但好象一般用GLOBALALLOC ,NEW,malloc就可以解決很多問題了,那為什麼還有virtualalloc及heapalloc呢 ,所以想對這幾個函數多瞭解一下,哪位大俠知道應該在什麼場合使用不同的函數呢?
其實沒有必要使用這麼多,使得程式過於難讀,使用new或GlobalAlloc這兩個函數就可以滿足須求了。HeapAlloc是從堆中分配記憶體,所分配的記憶體不需要使用GlobalLock來鎖住,而使用GlobalAlloc所分配的記憶體,如果在使用過程當中,分使用GlobalLock來鎖住,在使用完成後再GlobalUnlockTop 3 樓stzhou(阿毛)回複於 2001-02-04 12:14:00 得分 0
不同意zzh()的說法,記憶體的合理分配關係到應用程式的效率問題,不同的場合,不同的條件下對記憶體的分配有著特定的要求,絕不僅僅是new或GlobalAlloc這兩個函數可以解決了的。
另外GlobalAlloc(Win32下等於LocalAlloc)的得以儲存更多是考慮到了Win32與Win16的相容,這樣的記憶體空間在Free之前會一直處於調撥狀態。Top 4 樓edyang(化石)回複於 2001-02-04 20:44:00 得分 0
Heap 管理函數主要用於管理較小的記憶體塊(一般情況下認為是 < 4MB)。GlobalAlloc 一類的函數好像是 16bit API 的遺留物,WIN32 記憶體管理中部分全域和局部 Heap,只有一種屬於進程的 heap。VirtualAlloc 一類的函數是虛擬記憶體管理的。Top 5 樓sjy()回複於 2001-02-04 22:22:00 得分 0
剛好這兩天Top 6 樓sjy()回複於 2001-02-04 22:33:00 得分 0
我有空查了查書,1。說HEALPALLOC的用法是:先用CREATEHEAP建立一私人堆,(這個堆將會區別於已有程式的預設堆,而NEW,MALLOC,都是從程式的預設堆中分配,這是不同的,但使用這個私人堆而不用缺洎堆有什麼好處我就不清楚了。2,VIRTUALALLOC是用於管理虛存,可能分配較大塊的記憶體時比較好用,在需要時可以提交它將它調至實體記憶體進行操作。但GLOBALALLOC好象也是在GLOBALLOCK時才將記憶體鎖定在實體記憶體,好象差別也不大。我提這個問題是想加深對記憶體配置的瞭解,歡迎各位大俠進行討論,Top 7 樓bugn(unknown& whoami)回複於 2001-02-04 23:22:00 得分 40
對於不同場合用不同函數的問題edyang說得不錯。
對於GlobalAlloc我只知道有一種情況下要用就是CreateStreamOnHGlobal。另外CoTaskMemAlloc也是特定情況下非用不可的。
建議看看MSDN中有關文章,說得很明白的:
MSDN->Technical Articles->Windows Platform->Memory
to sjy:
> 而NEW,MALLOC,都是從程式的預設堆中分配,
這句話有問題,雖然書上這樣說過 :)
crt(malloc,new等)用的堆根據不同的crt實現有關,如果拿不準就去參考一下你用的crt的原始碼。現在一般的CRT的實現都有自己獨立的堆。GlobalAlloc/LocalAlloc/CoTaskMemAlloc/IMalloc都用的是預設堆,但這些函數在特定場合又不能用HeapAlloc(GetProcessHeap(), ...)來代替。
至於為什麼用私人堆,我記得Jeffey Richter的"Advanced Windows"裡是詳細講解過的。
==============================================================
globalalloc和malloc的區別樓主jco()2000-07-06 16:14:00 在 VC/MFC / 基礎類 提問
那位大蝦指點一二.
globalalloc和malloc的區別和各在什末情況下使用
1 樓hyena(hyena)回複於 2000-07-06 16:24:00 得分 0
個人觀點:
GlobalAlloc是一個Win32 API調用,只能在Win9x, WinNT上使用,
而malloc是一個ANSI C的標準運行庫函數,不但可以在Win9x、nt
上使用,還能在其他平台上使用。
從功能上看,二者完成的是一樣的功能Top 2 樓windoze(瞌睡窗)回複於 2000-07-06 16:32:00 得分 30
這兩個函數的功能完全不同。
GlobalAlloc在Win16中就已經有了,這個函數返回一個控制代碼,通過這個控制代碼,兩個進程可以共用一塊記憶體,DDE和剪貼簿就是通過這個函數交換資料的;malloc是一個庫函數,這個函數的功能,是通過內部調用了VirtualAlloc完成的,並且分配的記憶體不能共用。
一般來說,涉及到DDE和剪貼版的記憶體操作使用GlobalAlloc,大多數程式內部的記憶體操作,使用malloc
如果要使用大塊的共用記憶體,建議使用File Mapping
Top 3 樓WHQ()回複於 2000-07-06 16:34:00 得分 20
malloc等一類函數是執行階段程式庫提供了記憶體管理函數,它內部也是調用GlobalAlloc(WIN16)或32位VirtualAlloc之類的函數,因為GlobalAlloc及VirtualAlloc是以頁為單位分的,因此用malloc多次分配小塊記憶體時malloc會把它們合并成一次對GlobalAlloc或VirtualAlloc的調用,即malloc實際是做了一個簡單的記憶體管理Top 4 樓hyena(hyena)回複於 2000-07-06 16:51:00 得分 0
GlobalAlloc是為了與Win16相容才保留的,在Win32下不要使用Top 5 樓guojin(guojin)回複於 2000-07-06 17:49:00 得分 0
同意hyena
================================================================= malloc和calloc區別(c) 網上找到的英文解釋如下:
Both the malloc() and the calloc() functions are used to allocate dynamic memory. Each operates slightly different from the other.
Both the malloc() and the calloc() functions are used to allocate dynamic memory. Each operates slightly different from the other. malloc() takes a size and returns a pointer to a chunk of memory at least that big:
void *malloc( size_t size );
calloc() takes a number of elements, and the size of each, and returns a pointer to a chunk of memory
at least big enough to hold them all:
void *calloc( size_t numElements, size_t sizeOfElement );
There are one major difference and one minor difference between the two functions. The major difference is that malloc() doesn‘t initialize the allocated memory. The first time malloc() gives you a particular chunk of memory, the memory might be full of zeros. If memory has been allocated, freed, and reallocated, it probably has whatever junk was left in it. That means, unfortunately, that a program might run in simple cases (when memory is never reallocated) but break when used harder (and when memory is reused). calloc() fills the allocated memory with all zero bits. That means that anything there you are going to use as a char or an int of any length, signed or unsigned, is guaranteed to be zero. Anything you are going to use as a pointer is set to all zero bits.
That is usually a null pointer, but it is not guaranteed.Anything you are going to use as a float or double is set to all zero bits; that is a floating-point zero on some types of machines, but not on all.
The minor difference between the two is that calloc() returns an array of objects; malloc() returns one object. Some people use calloc() to make clear that they want an array.
下面是網上的中文說明
用malloc()函數更好還是用calloc()函數更好
函數malloc()和calloc()都可以用來動態分配記憶體空間,但兩者稍有區別。
malloc()函數有一個參數,即要分配的記憶體空間的大小:
void*malloc(size_tsize);
calloc()函數有兩個參數,分別為元素的數目和每個元素的大小,這兩個參數的乘積就是要分配的記憶體空間的大小。
void*calloc(size_tnumElements,size_tsizeOfElement);
如果調用成功,函數malloc()和函數calloc()都將返回所分配的記憶體空間的首地址。
函數malloc()和函數calloc() 的主要區別是前者不能初始化所分配的記憶體空間,而後者能。如果由malloc()函數分配的記憶體空間原來沒有被使用過,則其中的每一位可能都是0;反之, 如果這部分記憶體曾經被分配過,則其中可能遺留有各種各樣的資料。也就是說,使用malloc()函數的程式開始時(記憶體空間還沒有被重新分配)能正常進 行,但經過一段時間(記憶體空間還已經被重新分配)可能會出現問題。
函數calloc() 會將所分配的記憶體空間中的每一位都初始化為零,也就是說,如果你是為字元類型或整數類型的元素分配記憶體,那麽這些元素將保證會被初始化為0;如果你是為指 針類型的元素分配記憶體,那麽這些元素通常會被初始化為空白指標;如果你為實型資料分配記憶體,則這些元素會被初始化為浮點型的零。 |
|