淺談c語言中的堆


操作系統堆管理器管理

堆管理器是操作系統的一個模塊,堆管理內存分配靈活,按需分配。
 大塊內存

  堆內存管理者總量很大的操作系統內存塊,各進程可以按需申請使用,使用完釋放。
 程序手動申請&釋放:

  手工意思是需要寫代碼去申請malloc和釋放free。
 臟內存

  堆內存也是反復使用的,而且使用者用完釋放前不會清除,因此也是臟的。
 臨時性

  堆內存只在malloc和free之間屬於我這個進程,而可以訪問。在malloc之前和free之后
      都不能再訪問,否則會有不可預料的后果。

堆內存使用范例

(1)void *是個指針類型,malloc返回的是一個void *類型的指針,實質上malloc返回的是堆管理器分配給我本次申請的那段內存空間的首地址(malloc返回的值其實是一個數字,這個數字表示一個內存地址)。為什么要使用void *作為類型?主要原因是malloc幫我們分配內存時只是分配了內存空間,至於這段空間將來用來存儲什么類型的元素malloc是不關心的,由我們程序自己來決定。

(2)什么是void類型。void類型不表示沒有類型,而表示萬能類型。void的意思就是說這個數據的類型當前是不確定的,在需要的時候可以再去指定它的具體類型。void *類型是一個指針類型,這個指針本身占4個字節,但是指針指向的類型是不確定的,換句話說這個指針在需要的時候可以被強制轉化成其他任何一種確定類型的指針,也就是說這個指針可以指向任何類型的元素。

(3)malloc的返回值:成功申請空間后返回這個內存空間的指針,申請失敗時返回NULL。所以malloc獲取的內存指針使用前一定要先檢驗是否為NULL。

(4)malloc申請的內存時用完后要free釋放。free(p);會告訴堆管理器這段內存我用完了你可以回收了。堆管理器回收了這段內存后這段內存當前進程就不應該再使用了。因為釋放后堆管理器就可能把這段內存再次分配給別的進程,所以你就不能再使用了。

(5)再調用free歸還這段內存之前,指向這段內存的指針p一定不能丟(也就是不能給p另外賦值)。因為p一旦丟失這段malloc來的內存就永遠的丟失了(內存泄漏),直到當前程序結束時操作系統才會回收這段內存。

(6) malloc(0) malloc申請0字節內存本身就是一件無厘頭事情,一般不會碰到這個需要。 如果真的malloc(0)返回的是NULL還是一個有效指針?答案是:實際分配了16Byte的一段內存並且返回了這段內存的地址。這個答案不是確定的,因為C語言並沒有明確規定malloc(0)時的表現,由各malloc函數庫的實現者來定義。

   malloc(4) gcc中的malloc默認最小是以16B為分配單位的。如果malloc小於16B的大小時都會返回一個16字節的大小的內存。malloc實現時沒有實現任意自己的分配而是允許一些大小的塊內存的分配。    malloc(20)去訪問第25、第250、第2500····會怎么樣 實戰中:120字節處正確,1200字節處正確····終於繼續往后訪問總有一個數字處開始段錯誤了。

 1 #include <stdio.h>
 2 #include <stdlib.h>
 3  
 4  
 5 int main(void)
 6 {
 7     int *p = (int *)malloc(20);
 8     // 第二步:檢驗分配是否成功
 9     if (NULL == p)
10     {
11         printf("malloc error.\n");
12         return -1;
13     }
14     
15     *(p+3) = 12;
16     *(p+300000) = 1234;
17     printf("*(p+3) = %d.\n", *(p+3));
18     printf("*(p+300000) = %d.\n", *(p+300000));        
19     
20 
21 
22 /*
23     int *p1 = (int *)malloc(4);        // p2-p1 = 0x10 = 16Byte
24     int *p2 = (int *)malloc(4);
25 
26     printf("p1 = %p.\n", p1);        // p2-p1 = 0x10 = 16Byte
27     printf("p2 = %p.\n", p2);
28 */
29     
30 /*
31     int *p1 = (int *)malloc(0);
32     int *p2 = (int *)malloc(0);
33 
34     printf("p1 = %p.\n", p1);        // p2-p1 = 0x10 = 16Byte
35     printf("p2 = %p.\n", p2);
36     */
37 /*
38     // 需要一個1000個int類型元素的數組
39     
40     // 第一步:申請和綁定
41     int *p = (int *)malloc(1000*sizeof(int));
42     // 第二步:檢驗分配是否成功
43     if (NULL == p)
44     {
45         printf("malloc error.\n");
46         return -1;
47     }
48     
49     // 第三步:使用申請到的內存
50     //p = NULL;
51     //p = &a;    // 如果在free之前給p另外賦值,那么malloc申請的那段內存就丟失掉了
52                 // malloc后p和返回的內存相綁定,p是那段內存在當前進程的唯一聯系人
53                 // 如果p沒有free之前就丟了,那么這段內存就永遠丟了。丟了的概念就是
54                 // 在操作系統的堆管理器中這段內存是當前進程拿着的,但是你也用不了
55                 // 所以你想申請新的內存來替換使用,這就叫程序“吃內存”,學名叫內存泄漏
56     *(p+0) = 1;
57     *(p+1) = 2;
58     printf("*(p+0) = %d.\n", *(p+0));
59     printf("*(p+1) = %d.\n", *(p+1));                
60                     
61     *(p+222) = 133;
62     *(p+223) = 222;                
63                     
64     
65     // 第四步:釋放
66     free(p);
67     p = NULL;
68     
69     printf("*(p+222) = %d.\n", *(p+222));
70     printf("*(p+223) = %d.\n", *(p+223));
71 */
72     return 0;
73 }

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM