2011-11-08 78 views
6

我正在編寫一個測試動態內存分配的程序,以查看50%的規則有多好。50%規則

該程序有10,000個指針來動態分配內存塊。它還有一個數組來存儲每個塊的大小。它應該:

  1. 使用malloc()動態分配的內存塊的ptrList每個元素。這些塊應具有在1到10,000個字節範圍內隨機選擇的大小,塊大小應存儲在sizeList陣列中。
  2. 初始塊分配後,程序應該反覆釋放塊並分配新塊。這應該循環100,000次迭代。在每次迭代中,隨機選擇ptrList中的索引,將塊釋放,然後用具有隨機大小的新動態分配塊替換。
  3. 每完成100次迭代後,它應該打印出一行顯示迭代計數,近似堆大小(由任何塊中包含的最高和最低內存地址之間的差異確定)以及所有塊的總大小由ptrList指向的塊。

我有我的程序編碼,像這樣:

#include <stdio.h> 
#include <pthread.h> /* for pthreads */ 
#include <stdlib.h> /* for exit */ 

/** Number of memory blocks to allocate/deallocate. */ 
#define BLOCK_COUNT 10000 

/** Number of free/malloc operations to perform */ 
#define TEST_LENGTH 100000 

/** Maximum size of an allocated block. */ 
#define SIZE_LIMIT 10000 

int main(int argc, char *argv[]) { 
    // Array of pointers to all blocks that have been allocated. 
    char *ptrList[ BLOCK_COUNT ]; 

    // Array of sizes for each block, so we can know how much memory we're using. 
    int sizeList[ BLOCK_COUNT ]; 

    // Insert your code here 
    for (int j = 0; j < 1000; j++) { 

     int minimum = 0; 
     int maximum = 0; 
     int total = 0, remainder = 0; 

     for (int i = 0; i < BLOCK_COUNT; i++) { 
      int size = (rand() % SIZE_LIMIT) + 1; 
      ptrList[i] = malloc (size); 
      sizeList[i] = size; 
      total += size; 
      int heapsize = (int)ptrList[i]; 

      if (i == 0) { 
       maximum = heapsize; 
       minimum = heapsize; 
      } 
      else { 
       if (heapsize > maximum) { 
        maximum = heapsize; 
       } 
       if (heapsize < minimum) { 
        minimum = heapsize; 
       } 
      } 
     } 

     for (int i = 0; i < TEST_LENGTH; i++) { 
      int index = rand() % BLOCK_COUNT; 
      int size = (rand() % SIZE_LIMIT) + 1; 
      free(ptrList[index]); 
      total -= sizeList[index]; 
      ptrList[index] = malloc (size); 
      sizeList[index] = size; 
      total += sizeList[index]; 
      int heapsize = (int)ptrList[index]; 

      if (heapsize > maximum) { 
       maximum = heapsize; 
      } 
      if (heapsize < minimum) { 
       minimum = heapsize; 
      } 
     } 

     if (j > 0) { 
      remainder = j % 100; 
     } 

     if (remainder == 0) { 
      //printf("%d", example); 
      printf("%d %d %d\n", j, maximum - minimum, total); 
     } 

     for (int i = 0; i < BLOCK_COUNT; i++) { 
      free(ptrList[i]); 
     } 

    } 

    return 0; 
} 

很接近我的內存分配/釋放的正確方法?在我執行for循環之前,我的程序編譯並運行(沒有輸出),其中int j。它在我實現它之後掛起,所以也許有人可以幫我把問題固定在那裏。

編輯: 50%的規則是所有塊的總大小除以堆大小的近似值一般將在50%左右。

+3

「它在我實現它之後掛起」 - 這通常被認爲是一個問題... –

+0

@MitchWheat是的,我不太確定是什麼導致它。註釋掉for(int j = 0; j <1000; j ++)'允許程序運行完成。只要我重新註釋該行,程序就會掛起。我也嘗試在每次迭代結束時添加一個for循環來釋放內存。 – raphnguyen

+3

正如FYI一樣,隨機分配和釋放歷史上一直是程序內存使用的非常糟糕的模型。從這樣的實驗中可以得出很多可靠的結論。通過將分配器替換爲幾個大的進程(如Web瀏覽器(連續運行)或編譯器(在處理文件後結束)),您可能會獲得更多有趣的數據。 –

回答

4

除了死鎖(代碼過多的代碼),你在變量和循環方面還存在一些問題:你的for (int i = 0; i < TEST_LENGTH; i++)...循環實現了規範的第2步,循環中每100步應該打印當前的統計數據。有一個外部for (int j = 0; j < 1000; j++)循環和測試j%100殘餘是無稽之談。

爲了調試像這樣的問題,敲兩個或三個零關每個大的數字BLOCK_COUNT,TEST_LENGTH,SIZE_LIMIT中,j循環限制更改爲10,並添加後printf("j=..." ...)for (int j ...) {,所以你可以告訴發生了什麼。有了這樣的變化,你會看到:

j=0 0 0 
    0 556736 507760 
    j=1 0 0 
    j=2 0 0 
    j=3 0 0 
    ... 

,然後可以斷定你的程序似乎掛起,因爲它是慢慢數Ĵ高達100去j%100 == 0

現在我會提到兩個小的刪除項目,之後會提到您的程序的一個主要問題。

代替

int minimum = 0; 
    int maximum = 0; 
    ... 
    if (i == 0) { 
     maximum = heapsize; 
     minimum = heapsize; 
    } 
    else { 
     if (heapsize > maximum) { 
      maximum = heapsize; 
    } 
    if (heapsize < minimum) { 
      minimum = heapsize; 
    } 

int minimum = MAX_INT; 
    int maximum = 0; 
    ... 
    if (heapsize > maximum) 
     maximum = heapsize; 
    if (heapsize < minimum) 
     minimum = heapsize; 

(或者可能是MAX_INT的變體)和(如果你需要j和/或remainder,你沒有),而不是

if (j > 0) { 
     remainder = j % 100; 
    } 

    if (remainder == 0) { 
    ... 

你會寫

if (j>0 && j%100 == 0) { 
    ... 

程序的一個主要問題:當您在第2部分中說free(ptrList[index]);時,可能會釋放佔當前最小或最大內存地址的項目。解決這個問題的一種方法是維護具有最小/最大值和fifo規則的優先級隊列;我認爲,你會發現更簡單的是,在分配時不跟蹤最小/最大值,而是在每次打印之前找到最小/最大值的循環。

程序的一個小問題:某些索引使用的最大地址不是ptrList[index],而是ptrList[index]+sizeList[index]

+0

謝謝,我最初有'if(j == 0 || j%100 == 0)',但程序不喜歡這個。我會嘗試通過我的代碼並刪除儘可能多的垃圾,但現在我陷入了最小的問題。 SIZE_LIMIT被限制爲10000,並且堆大小必須大於'max - min'在'98,000,000'範圍內的大小。多次運行我的程序,最大堆大小會發生變化,但最小堆大小保持不變,我似乎無法確定錯誤在邏輯中的位置。 – raphnguyen

+0

在我編輯第二段到最後一段時,您可能已經寫過該評論,請注意最小/最大問題。 Re「SIZE_LIMIT限於...」只是將常量改爲任何在調試時易於使用的東西,例如,只有3或4個字符與半個數兆字節的塊一起傳遞,因此您可以打印所有大小並手動檢查;當一切正常時,將常量修正爲所需的值。 –

+0

謝謝,我已經在打印前刪除了'min'和'max'。我仍然遇到'最低限度「問題。也許我正在計算最低限度的錯誤方式?分數堆大小(最大 - 最小)/總數?最大值似乎沒問題,但我無法檢查其他值。 – raphnguyen