2D数组内存分配(malloc)返回NULL

时间:2017-02-18 22:13:06

标签: c++ arrays memory-management malloc

我正在尝试使用 GCC 编译 64位CPP代码,但是一旦我增加了多维(即2D)数组内存分配就会返回NULL元素大小从 46,000 46,500 。我的虚拟内存设置为96GB,硬件使用32GB Ram运行64位操作系统。 只要 MAX_VERTICES 不超过 46000,代码就可以正常运行。

以下是我试图动态分配的内容:

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 个答案:

答案 0 :(得分: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]; } 检查是否可以分配所有数组元素并释放分配的内容(如果没有,而不是尝试在调用者函数中清理)会更加一致。

这是一个更一致的版本和调用代码:

new

编辑作为 MM 发表评论时,您应该使用C ++中的deletemalloc()运算符代替free()和{{ 1}}。 (或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];
}