c++ - 二维数组内存分配 (malloc) 返回 NULL

标签 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
}

最佳答案

函数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存储到全局指针中会更安全。
  • 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 评论的那样,您应该在 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];
}

关于c++ - 二维数组内存分配 (malloc) 返回 NULL,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42321273/

相关文章:

c++ - Qt5 : error: ‘qt_metacall’ is not a member of

android - 使用android的OpenCV构建库在 “not building target XXX because there was no build command for it”上失败

javascript - 如何在Vue中立即提交后显示评论而不渲染页面

java 没有正确地保留巨大的初始堆大小

c++ - 如何在任务计划程序中显示所有任务

c++ - 分段故障。是因为坏指针吗?

ios - 如何在 swift 中创建一个由类实例填充的数组?

javascript - 命名;在javascript中动态创建变量

C++ 堆栈使用模板化链表 - 内存泄漏

c - 我们是否需要释放 GLIB 列表中的每个元素