2017-02-18 38 views
1

我試圖編譯使用GCC一個64位CPP代碼,然而多維(即2D)陣列的存儲器分配返回NULL一次我從46000增大元件尺寸46,500。我的虛擬內存設置爲96GB,並且硬件正在運行使用32GB Ram的64位操作系統。 只要MAX_VERTICES不超過46000代碼工作正常。2D陣列內存分配(malloc的)返回NULL

以下是我試圖動態分配:

struct ShortestPath { 
    real32 totalWeight; 
    // NOTE: ShortestPath is a list of pointers; does not make copies 
    // (i.e. side-effects) the pointers point to memory allocated 
    // in the DijkstraSPTree array in the vehicle_searching module 
    List<DirectedEdge *> *edgeList; 
}; 

#define MAX_VERTICES 46500 
global_variable ShortestPath spAllPairs[MAX_VERTICES][MAX_VERTICES]; 

在堆上分配內存用下面的代碼替換

spAllPairs[MAX_VERTICES][MAX_VERTICES] 

global_variable ShortestPath **spAllPairs; 
global_variable ShortestPath *arr_data; 

ShortestPath *getShortestPath(EdgeWeightedDigraph *digraph, int32 source, 
           int32 dest) 
{ 
    free(spAllPairs); // Function is called multiple times so I clear memory 
    free(arr_data); // before reallocation given values pointed by pointers 
    free(spTreesArray); // are used in other files in my project after run. 

    inline allocate_mem(ShortestPath*** arr, ShortestPath** arr_data, int n, int m); 
    allocate_mem(&spAllPairs, &arr_data, MAX_VERTICES, MAX_VERTICES); 
    for (unsigned int k = 0 ; k < MAX_VERTICES ; k++) { 
     if (spAllPairs[k] == NULL) { 
      while (k >= 1) { 
       free(spAllPairs[k]); 
       --k; 
      } 
      free(spAllPairs[0]); 
      free(spAllPairs); 
      fprintf(stderr, "Failed to allocate space for Shortest Path Pairs!\n"); 
      exit(1); 
     } 
    } 

    spTreesArray = (DijkstraSPTree *)malloc(MAX_VERTICES * sizeof(DijkstraSPTree)); 
    for (int32 vertexTo = 0; vertexTo < digraph->vertices; ++vertexTo) { 
     pathTo(&spTreesArray[source], &spAllPairs[source][vertexTo], 
        vertexTo); 
    } 
    return &spAllPairs[source][dest]; 
} 

void pathTo(DijkstraSPTree *spTree, ShortestPath *shortestPath, int32 dest) 
{ 
    List<DirectedEdge *>::traverseList(freeDirectedEdge, shortestPath->edgeList); 
    List<DirectedEdge *>::emptyList(&shortestPath->edgeList); 
    shortestPath->totalWeight = spTree->distTo[dest]; 
} 

int allocate_mem(ShortestPath ***arr, ShortestPath **arr_data, int n, int m) 
{ 
    *arr = (ShortestPath **)malloc(n * sizeof(ShortestPath*)); 
    *arr_data = (ShortestPath *)malloc(n * m * sizeof(ShortestPath)); 
    for (int i = 0; i < n; i++) 
     (*arr)[i] = *arr_data + i * m; 
    return 0; //free point 
} 
+1

請記住,在堆分配必須是連續的* *。你試圖分配32個內存(如果'sizeof(ShortestPath)== 16'最有可能)作爲一個大塊。如果沒有這麼大的連續內存塊,分配將失敗。 –

+0

'46000 x 46000'低於1.97 Gigs,而'46500 x 46500'是2.013 Gig。如果你的結構體的大小是16,那麼'46000'可能會保持在32GB以下,而46500的產量超過32GB。檢查你的'mallocs'的結果,他們應該得到NULL在某些時候 –

+0

@StephanLechner物理內存應該不重要,因爲我使用的是malloc,而虛擬內存是96GB。我不確定它是否是連續的。在「spAllPairs」的初始化期間,我在46500x46500處獲得NULL。 – Far

回答

0

的功能allocate_memgetShortestPath中用於釋放結構的代碼不一致。如果arr_data在其他地方沒有使用,你應該刪除這個全局變量和分配間接數組是這樣的:

ShortestPath **allocate_mem(int n, int m) { 
    ShortestPath **arr = (ShortestPath **)calloc(n, sizeof(*arr)); 
    if (arr != NULL) { 
     for (int i = 0; i < n; i++) { 
      arr[i] = (ShortestPath *)calloc(m, sizeof(ShortestPath)); 
      if (arr[i] == NULL) 
       break; 
     } 
    } 
    return arr; 
} 

注:

  • 這將是更安全的存儲NULL進入全球指針後,你free他們指向的內存。
  • 對於allocate_mem來說,檢查它是否可以分配所有數組元素並釋放分配給它的分配元素(如果沒有),而不是嘗試清除調用者函數,會更加一致。

這裏是一個比較一致的版本,並調用代碼:

ShortestPath **allocate_mem(int n, int m) { 
     ShortestPath **arr = (ShortestPath **)calloc(n, sizeof(*arr)); 
     if (arr != NULL) { 
      for (int i = 0; i < n; i++) { 
       arr[i] = (ShortestPath *)calloc(m, sizeof(ShortestPath)); 
       if (arr[i] == NULL) { 
        for (j = i; j-- > 0;) { 
         free(arr[j]); 
        } 
        free(arr); 
        return NULL; 
       } 
      } 
     } 
     return arr; 
    } 

    ShortestPath *getShortestPath(EdgeWeightedDigraph *digraph, int32 source, 
            int32 dest) 
    { 
     // Function is called multiple times so I clear memory 
     // before reallocation given values pointed by pointers 
     // are used in other files in my project after run. 
     free(spAllPairs); 
     spAllPairs = NULL; 
     free(arr_data); 
     arr_data = NULL; 
     free(spTreesArray); 
     spTreesArray = NULL; 

     spAllPairs = allocate_mem(MAX_VERTICES, MAX_VERTICES); 
     if (spAllPairs == NULL) { 
      fprintf(stderr, "Failed to allocate space for Shortest Path Pairs!\n"); 
      exit(1); 
     } 

     spTreesArray = (DijkstraSPTree *)malloc(MAX_VERTICES * sizeof(DijkstraSPTree)); 
     if (spTreesArray == NULL) { 
      fprintf(stderr, "Failed to allocate space for DijkstraSPTree!\n"); 
      exit(1); 
     } 
     for (int32 vertexTo = 0; vertexTo < digraph->vertices; ++vertexTo) { 
      pathTo(&spTreesArray[source], &spAllPairs[source][vertexTo], 
        vertexTo); 
     } 
     return &spAllPairs[source][dest]; 
    } 

編輯M.M評論說,你應該在C使用newdelete運營++而不是malloc()free()。 (或除malloc,但爲什麼與malloc打擾反正):

ShortestPath **allocate_mem(int n, int m) { 
    ShortestPath **arr = new ShortestPath *[n]; 
    if (arr != NULL) { 
     for (int i = 0; i < n; i++) { 
      arr[i] = new ShortestPath[m]; 
      if (arr[i] == NULL) { 
       for (j = i; j-- > 0;) { 
        delete[] arr[j]; 
       } 
       delete[] arr; 
       return NULL; 
      } 
     } 
    } 
    return arr; 
} 

ShortestPath *getShortestPath(EdgeWeightedDigraph *digraph, int32 source, 
           int32 dest) 
{ 
    // Function is called multiple times so I clear memory 
    // before reallocation given values pointed by pointers 
    // are used in other files in my project after run. 
    delete[] spAllPairs; 
    spAllPairs = NULL; 
    delete[] spTreesArray; 
    spTreesArray = NULL; 

    spAllPairs = allocate_mem(MAX_VERTICES, MAX_VERTICES); 
    if (spAllPairs == NULL) { 
     fprintf(stderr, "Failed to allocate space for Shortest Path Pairs!\n"); 
     exit(1); 
    } 

    spTreesArray = new DijkstraSPTree *[MAX_VERTICES]; 
    if (spTreesArray == NULL) { 
     fprintf(stderr, "Failed to allocate space for DijkstraSPTree!\n"); 
     exit(1); 
    } 
    for (int32 vertexTo = 0; vertexTo < digraph->vertices; ++vertexTo) { 
     pathTo(&spTreesArray[source], &spAllPairs[source][vertexTo], 
       vertexTo); 
    } 
    return &spAllPairs[source][dest]; 
} 
+0

這是未定義的行爲,使用malloc-family然後寫入空間,而不通過placement-new創建對象。 (所以你應該首先使用'new')。 –

+0

錯誤:'(* arr)[i] = new ShortestPath [m];'不匹配'operator ='操作數類型是'ShortestPath'和'ShortestPath *' – Far

+0

剛剛用2d向量代替2d數組,魅力。沒有必要使用malloc並使代碼複雜化。 – Far