2017-02-18 22 views
1

Я пытаюсь скомпилировать 64-битного кода CPP с использованием GCC, однако многомерное (т.е. 2D) распределение памяти массив возвращает NULL раз увеличить размер элемента из до . Моя виртуальная память установлена ​​на 96 ГБ, а на оборудовании работает 64-разрядная ОС с 32 ГБ памяти. Код работает нормально, покаMAX_VERTICESне превышает46000.2D Выделение массива памяти (таНос) Возвращает 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]; 

Выделяют память на Heap заменить

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 концерта, тогда как' 46500 x 46500' составляет 2,013 концерта. Если размер вашей структуры равен 16, то «46000» может оставаться ниже 32 ГБ, тогда как 46500 дает более 32 ГБ. Проверьте результаты вашего 'mallocs', они должны получить NULL в какой-то момент –

+0

@StephanLechner Физическая память не имеет значения, так как я использую malloc, а виртуальная память - 96 ГБ. Я не уверен, что это смежно. Я получаю NULL при 46500x46500 во время инициализации «spAllPairs». – Far

ответ

0

функция allocate_mem не соответствует коду, используемому в getShortestPath, чтобы освободить структуры. Если 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]; 
    } 

EDIT в M.M комментировал, вы должны использовать new и delete операторы в C++ вместо 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, а затем запись в пространство, без создания объектов через place-new. (Таким образом, вы должны использовать 'new' в первую очередь). –

+0

Ошибка: '(* arr) [i] = new ShortestPath [m];' no match for 'operator =' Типы операндов: 'ShortestPath' и' ShortestPath * ' – Far

+0

Просто заменил 2d-массив на 2d-вектор, и он работает как Шарм. Нет необходимости использовать malloc и еще больше усложнить код. – Far

 Смежные вопросы

  • Нет связанных вопросов^_^